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

iOS应用通过“打开方式”接收PDF真机无响应问题求助

iOS应用接收PDF文档真机异常问题

我开发了一款可从其他应用接收PDF的iOS应用,在Xcode模拟器中运行正常,但部署到真实iPhone设备后,虽然设备会将我的应用列入可接收PDF的应用列表,选择后应用会启动,但无法处理该PDF文档。

当前实现使用DocumentGroup,代码如下:

应用入口代码

@main
struct ScannerImporterApp: App {
    var body: some Scene {
        DocumentGroup(newDocument: ScannerImporterDocument()) { file in
            ContentView(doc_name: file.document.title, doc_content: file.document.text)
        }

        WindowGroup {
            ContentView(doc_name: "", doc_content: "")
         }
    }
}

文档管理类代码

extension UTType {
    static var exampleText: UTType {
        UTType(importedAs: "com.adobe.pdf")
    }
}

struct ScannerImporterDocument: FileDocument 
{
    var text: String
    var title: String
    
    init(title: String = "My title", text: String = "Hello, world!") 
    {
        print("TestDocument : init")
        self.title = title
        self.text = text
    }
    
    static var readableContentTypes: [UTType] { [.exampleText] }
    
    init(configuration: ReadConfiguration) throws {
        
        print("TestDocument : init 2")
        let data = configuration.file.regularFileContents
        
        title = configuration.file.filename!
        text = (data?.base64EncodedString())!
    }
    
    func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
        print("TestDocument : init 3")
        let data = text.data(using: .utf8)!
        return .init(regularFileWithContents: data)
    }
}

模拟器中,应用启动时会显示文件选择器,从其他应用发送PDF时,会创建ScannerImporterDocument实例并通过configuration传入内容处理。但真机上,应用启动显示文件选择器,接收PDF时仅切换到前台,停留在文件选择器界面,无法处理文档。

我不需要应用启动时显示文件选择器,不使用DocumentGroup的方案也可接受,求解决方法。


解决方案

方案一:修复DocumentGroup问题并移除启动文件选择器

  1. 替换DocumentGroup构造器
    原代码中newDocument参数会触发默认文件选择器,改用viewing构造器仅处理导入的文档:

    @main
    struct ScannerImporterApp: App {
        var body: some Scene {
            DocumentGroup(viewing: ScannerImporterDocument.self) { file in
                ContentView(doc_name: file.document.title, doc_content: file.document.text)
            }
            WindowGroup {
                ContentView(doc_name: "", doc_content: "")
            }
        }
    }
    
  2. 修正UTType定义
    直接使用系统内置的PDF类型,避免自定义导入可能的兼容性问题:

    extension UTType {
        static var pdf: UTType { UTType.pdf }
    }
    
    struct ScannerImporterDocument: FileDocument {
        // ... 其他代码不变
        static var readableContentTypes: [UTType] { [.pdf] }
        // ... 其他代码不变
    }
    
  3. 增加空值安全处理
    真机环境下filename和regularFileContents可能为空,需添加校验:

    init(configuration: ReadConfiguration) throws {
        print("TestDocument : init 2")
        guard let data = configuration.file.regularFileContents else {
            throw NSError(domain: "ImporterError", code: 1, userInfo: [NSLocalizedDescriptionKey: "无法读取文件内容"])
        }
        title = configuration.file.filename ?? "未知PDF"
        text = data.base64EncodedString()
    }
    

方案二:不使用DocumentGroup,通过应用代理处理导入

如果完全不想依赖DocumentGroup,可以通过应用代理直接捕获文件导入事件:

  1. 实现UIApplicationDelegate

    class AppDelegate: NSObject, UIApplicationDelegate {
        func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
            guard url.isFileURL, url.pathExtension.lowercased() == "pdf" else { return false }
            
            do {
                let data = try Data(contentsOf: url)
                let userInfo = [
                    "title": url.lastPathComponent,
                    "content": data.base64EncodedString()
                ] as [String: Any]
                NotificationCenter.default.post(name: .pdfImported, object: nil, userInfo: userInfo)
            } catch {
                print("读取PDF失败:\(error.localizedDescription)")
            }
            return true
        }
    }
    
    extension Notification.Name {
        static let pdfImported = Notification.Name("PDFImported")
    }
    
  2. 修改App入口并绑定代理

    @main
    struct ScannerImporterApp: App {
        @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
        
        var body: some Scene {
            WindowGroup {
                ContentView(doc_name: "", doc_content: "")
                    .onReceive(NotificationCenter.default.publisher(for: .pdfImported)) { note in
                        guard let title = note.userInfo?["title"] as? String,
                              let content = note.userInfo?["content"] as? String else { return }
                        // 这里可以通过@State或ObservableObject更新ContentView的显示内容
                    }
            }
        }
    }
    
  3. 配置Info.plist添加文档支持
    确保Info.plist中声明支持PDF类型:

    <key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeName</key>
            <string>PDF Document</string>
            <key>LSHandlerRank</key>
            <string>Alternate</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>com.adobe.pdf</string>
            </array>
        </dict>
    </array>
    

关键注意事项

  • 真机测试需确保应用签名有效,且设备已信任开发者证书
  • 所有文件操作必须添加错误处理,避免空值或权限问题导致崩溃
  • 方案二中建议使用ObservableObject管理PDF数据,比Notification更易维护

内容的提问来源于stack exchange,提问作者Brice

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 01:16:01