You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 08:54:56