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问题并移除启动文件选择器
替换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: "") } } }修正UTType定义
直接使用系统内置的PDF类型,避免自定义导入可能的兼容性问题:extension UTType { static var pdf: UTType { UTType.pdf } } struct ScannerImporterDocument: FileDocument { // ... 其他代码不变 static var readableContentTypes: [UTType] { [.pdf] } // ... 其他代码不变 }增加空值安全处理
真机环境下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,可以通过应用代理直接捕获文件导入事件:
实现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") }修改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的显示内容 } } } }配置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
相关产品推荐
相关产品推荐

