SwiftUI文档型应用:视图显示前初始化文档数据问询
解决方案:SwiftUI文档URL预加载与视图初始化处理
核心方案
通过启动加载页完成文档URL的所有预处理(包括图片URL组合、视频内容解析等),待处理完成后再渲染主视图。同时使用ObservableObject管理数据状态,确保视图仅在数据就绪后加载。
1. 重构数据管理类
创建ObservableObject子类,负责文档加载、URL预处理逻辑,替代直接在Doc结构体中处理的方式:
import SwiftUI // 扩展Doc,新增视频URL字段(按需调整) struct Doc: Codable { var images: [URL] var videos: [URL] = [] init(images: [URL], videos: [URL] = []) { self.images = images self.videos = videos } } // 数据管理类:处理文档加载、URL预处理 class DocDataManager: ObservableObject { @Published var processedDoc: Doc? @Published var isLoading = true // 加载并预处理文档 func loadAndProcessDocument(_ document: TestInitialiseFromDocDocument) { DispatchQueue.global(qos: .userInitiated).async { // 模拟生产环境的多项预处理操作 let processedImages = self.processImageURLs(document.document.images) let processedVideos = self.processVideoURLs(document.document.videos) DispatchQueue.main.async { self.processedDoc = Doc(images: processedImages, videos: processedVideos) self.isLoading = false } } } // 图片URL处理逻辑(示例:补全域名、格式转换等) private func processImageURLs(_ urls: [URL]) -> [URL] { return urls.map { url in // 这里替换为实际处理逻辑,比如拼接基础域名 let baseURL = URL(string: "https://your-domain.com/")! return baseURL.appending(path: url.path) } } // 视频URL处理逻辑(示例:解析流媒体地址、验证有效性等) private func processVideoURLs(_ urls: [URL]) -> [URL] { return urls.filter { url in // 这里替换为实际视频URL验证逻辑 url.pathExtension == "mp4" || url.pathExtension == "mov" } } }
2. 实现启动加载视图与主视图切换
创建加载视图,在数据预处理完成后自动切换到主视图:
struct ContentView: View { @StateObject private var dataManager = DocDataManager() @State private var document: TestInitialiseFromDocDocument = .init() var body: some View { Group { if dataManager.isLoading { // 启动加载页:展示加载动画或提示 VStack { ProgressView("正在处理资源...") .scaleEffect(1.2) Text("请稍候") .padding(.top, 10) } .onAppear { // 应用启动时立即开始处理文档 dataManager.loadAndProcessDocument(document) } } else { // 主视图:使用预处理后的文档数据 MainView(doc: dataManager.processedDoc!) } } } } // 主视图示例:展示处理后的图片和视频 struct MainView: View { let doc: Doc var body: some View { ScrollView { VStack(spacing: 20) { Text("处理后的图片URL") .font(.title) ForEach(doc.images, id: \.self) { url in Text(url.absoluteString) .padding() .background(Color.gray.opacity(0.1)) .cornerRadius(8) } Text("处理后的视频URL") .font(.title) ForEach(doc.videos, id: \.self) { url in Text(url.absoluteString) .padding() .background(Color.blue.opacity(0.1)) .cornerRadius(8) } } .padding() } } }
3. 调整文档读取逻辑
修改TestInitialiseFromDocDocument的初始化方法,确保读取文档后能传递给数据管理类处理:
struct TestInitialiseFromDocDocument: FileDocument, Codable { var document: Doc init() { // 测试数据:可替换为实际文档内容 let imageA = URL(string: "assets/imageA.jpg")! let imageB = URL(string: "assets/imageB.png")! let videoA = URL(string: "assets/videoA.mp4")! let videoB = URL(string: "assets/videoB.txt")! // 无效视频格式,会被过滤 let newDoc = Doc(images: [imageA, imageB], videos: [videoA, videoB]) self.document = newDoc } static var readableContentTypes: [UTType] { [.exampleText] } init(configuration: ReadConfiguration) throws { guard let data = configuration.file.regularFileContents else { throw CocoaError(.fileReadCorruptFile) } let fileContents = try JSONDecoder().decode(Self.self, from: data) self = fileContents } func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper { let data = try JSONEncoder().encode(self) return .init(regularFileWithContents: data) } }
额外说明
- 用户添加新URL后,只需调用
dataManager.loadAndProcessDocument(newDocument)即可重新触发预处理逻辑,视图会自动更新。 - 预处理逻辑(
processImageURLs、processVideoURLs)可根据生产需求扩展,比如添加缓存、错误处理、异步下载预览图等。
内容的提问来源于stack exchange,提问作者user1542125
相关产品推荐
相关产品推荐

