如何解决关闭UIDocumentPickerViewController时的报错问题
我正在开发iOS应用,通过UIDocumentPickerViewController允许用户从Files app选择PDF文件并保存到应用文档目录。目前已实现打开选择器和选择文件的功能,但关闭选择器时出现报错:
"[DocumentManager] The view service did terminate with error: Error Domain=_UIViewServiceErrorDomain Code=1 "(null)" UserInfo={Terminated=disconnect method}"
相关UIViewController代码如下:
import UIKit import CoreData import PDFKit import MobileCoreServices import UniformTypeIdentifiers class AddDocumentViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIDocumentPickerDelegate { @IBAction func chooseFile (_ sender: UIButton) { fileTypeSelectionInput = fileTypeSelection.selectedSegmentIndex var documentPicker: UIDocumentPickerViewController! if #available(iOS 14, *) { // iOS 14 & later let supportedTypes: [UTType] = [UTType.pdf] documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: supportedTypes) } else { // iOS 13 or older code let supportedTypes: [String] = [kUTTypeImage as String] documentPicker = UIDocumentPickerViewController(documentTypes: supportedTypes, in: .import) } documentPicker.delegate = self documentPicker.allowsMultipleSelection = false documentPicker.modalPresentationStyle = .formSheet self.present(documentPicker, animated: true) } func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { let fileURL = urls[0] var fileName = urls[0].lastPathComponent subjectFileName = fileName let filePath = getDocumentsDirectory().appendingPathComponent(fileName) print(fileName) guard fileURL.startAccessingSecurityScopedResource() else { // Handle denied access return } defer { fileURL.stopAccessingSecurityScopedResource() } do { guard let document = PDFDocument(url: fileURL) else { print("Error: could not create PDFDocument from url") return } document.write(to: filePath) print ("success") } catch let error { print("error: \(error)") } } func getDocumentsDirectory() -> URL { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) return paths[0] } }
我怀疑该报错和iCloud能力有关,毕竟Files中的文件可能存储在个人iCloud中,但我仅需将文件保存到应用本地文档目录,不需要同步到iCloud。我已经按照Apple文档配置了iCloud能力,报错仍然存在,求解决思路。
解决思路
修复iOS13及以下版本的类型错误
当前iOS13分支里设置的supportedTypes是[kUTTypeImage as String],但你需要的是PDF文件,应该改成[kUTTypePDF as String],类型不匹配可能导致文档选择器出现异常。统一文档选择器的初始化模式
iOS14+你用的是forOpeningContentTypes,该模式默认是查看而非导入操作。如果你需要将文件复制到本地,建议iOS14+也使用forImportingContentTypes,明确导入意图,避免权限或资源访问冲突。修改后代码:if #available(iOS 14, *) { let supportedTypes: [UTType] = [UTType.pdf] documentPicker = UIDocumentPickerViewController(forImportingContentTypes: supportedTypes) } else { let supportedTypes: [String] = [kUTTypePDF as String] documentPicker = UIDocumentPickerViewController(documentTypes: supportedTypes, in: .import) }移除不必要的iCloud配置
既然不需要iCloud功能,直接在Xcode项目的Signing & Capabilities中删除iCloud相关配置项即可。多余的配置反而可能引发不必要的冲突,该报错并非必须依赖iCloud配置解决。优化文件复制逻辑
当前用PDFDocument.write(to:)保存文件,可替换为FileManager原生复制方法,更直接且避免PDFKit潜在问题:do { try FileManager.default.copyItem(at: fileURL, to: filePath) print("文件保存成功") } catch { print("复制文件失败:\(error)") }补充取消选择的代理方法
实现documentPickerWasCancelled方法,处理用户取消选择的场景,避免未正确关闭选择器导致的异常:func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) { controller.dismiss(animated: true) }
内容的提问来源于stack exchange,提问作者Nicholas Farmer

