SwiftUI中添加两个viewing模式DocumentGroup报“Extra argument in call”错误
解决SwiftUI中多个
DocumentGroup(viewing:)共存的构建错误 问题原因
SwiftUI的SceneBuilder在处理多个DocumentGroup(viewing:)实例时会触发"Extra argument in call"错误,本质是因为每个DocumentGroup(viewing:)的泛型参数(对应不同的只读文档类型)不同,编译器无法正确推断多个不同泛型类型的DocumentGroup组成的场景集合类型,导致类型解析失败。而newDocument:初始化器的DocumentGroup因为泛型参数一致(或编译器能统一处理),所以可以正常共存。
解决方案
方案1:整合只读文档类型到单一DocumentGroup
将多种只读文档类型统一到一个ReferenceFileDocument(或FileDocument)实现中,通过文档类型判断加载对应视图,避免添加多个DocumentGroup(viewing:)。
示例代码:
import SwiftUI import UniformTypeIdentifiers // 定义文档类型标识符枚举 enum ReadOnlyDocType: String { case typeA = "com.yourapp.doc-typea" case typeB = "com.yourapp.doc-typeb" } // 通用只读文档实现 struct UnifiedReadOnlyDoc: ReferenceFileDocument { static var readableContentTypes: [UTType] { [UTType(ReadOnlyDocType.typeA.rawValue)!, UTType(ReadOnlyDocType.typeB.rawValue)!] } let url: URL let docType: ReadOnlyDocType init(configuration: ReadConfiguration) throws { self.url = configuration.fileURL guard let utID = configuration.contentType.identifier, let type = ReadOnlyDocType(rawValue: utID) else { throw CocoaError(.fileReadCorruptFile) } self.docType = type } func snapshot(contentType: UTType) throws -> URL { url } func fileWrapper(snapshot: URL, configuration: WriteConfiguration) throws -> FileWrapper { throw CocoaError(.fileWriteNoPermission) // 只读文档,无需实现写入逻辑 } } // App结构体中使用单一只读DocumentGroup @main struct YourApp: App { var body: some Scene { // 可编辑文档组 DocumentGroup(newDocument: EditableDoc()) { file in EditableDocView(document: file.$document) } // 整合后的只读文档组 DocumentGroup(viewing: UnifiedReadOnlyDoc.self) { file in switch file.document.docType { case .typeA: ReadOnlyTypeAView(url: file.document.url) case .typeB: ReadOnlyTypeBView(url: file.document.url) } } } }
方案2:用WindowGroup配合文档选择器替代多DocumentGroup
如果不想整合文档类型,可通过WindowGroup结合UIKit的UIDocumentPickerViewController手动管理不同类型的只读文档加载,绕过DocumentGroup的限制。
示例代码:
import SwiftUI import UniformTypeIdentifiers import UIKit // 包装UIDocumentPickerViewController struct DocPicker: UIViewControllerRepresentable { let allowedTypes: [UTType] let onSelect: (URL) -> Void func makeUIViewController(context: Context) -> UIDocumentPickerViewController { let picker = UIDocumentPickerViewController(forOpeningContentTypes: allowedTypes) picker.delegate = context.coordinator return picker } func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, UIDocumentPickerDelegate { let parent: DocPicker init(_ parent: DocPicker) { self.parent = parent } func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { guard let url = urls.first else { return } parent.onSelect(url) } } } // 让URL支持Identifiable,用于sheet(item:) extension URL: Identifiable { public var id: String { absoluteString } } @main struct YourApp: App { @State private var showTypeAPicker = false @State private var showTypeBPicker = false @State private var selectedTypeAURL: URL? @State private var selectedTypeBURL: URL? var body: some Scene { // 可编辑文档组 DocumentGroup(newDocument: EditableDoc()) { file in EditableDocView(document: file.$document) } // 自定义只读文档入口 WindowGroup { VStack(spacing: 20) { Button("打开Type A文档") { showTypeAPicker = true } Button("打开Type B文档") { showTypeBPicker = true } } .sheet(isPresented: $showTypeAPicker) { DocPicker(allowedTypes: [UTType("com.yourapp.doc-typea")!]) { url in selectedTypeAURL = url showTypeAPicker = false } } .sheet(item: $selectedTypeAURL) { url in ReadOnlyTypeAView(url: url) } .sheet(isPresented: $showTypeBPicker) { DocPicker(allowedTypes: [UTType("com.yourapp.doc-typeb")!]) { url in selectedTypeBURL = url showTypeBPicker = false } } .sheet(item: $selectedTypeBURL) { url in ReadOnlyTypeBView(url: url) } } } }
内容的提问来源于stack exchange,提问作者jkcl
相关产品推荐
相关产品推荐

