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

使用UINavigationItemRenameDelegate重命名UIDocument的问题排查

解决UIDocumentBrowserViewController打开文档的重命名问题

核心问题说明

苹果官方应用(如Pages、Numbers)并非使用私有API或特殊权限实现文档重命名,而是遵循了UIDocumentBrowserViewController的官方工作流。沙箱限制确实会阻止直接通过NSFileCoordinator或NSFileManager重命名文件,但UIDocumentBrowserViewController本身提供了专门的API来处理这类操作,因为它能正确管理系统级的文件访问权限。

必要配置确认

你当前的Info.plist和权限配置基本正确,但需重点确认以下两点:

  • LSSupportsOpeningDocumentsInPlace必须设为true:该配置允许应用直接编辑原位文件,是实现重命名的前提。
  • 权限配置中,com.apple.security.read-write.user-selected已启用即可,无需同时保留read-only版本(两者共存不影响,但只读权限无实际作用)。

修复WWDC代码片段的错误

你遇到的视图服务崩溃错误,根源是使用了新的UIDocumentBrowserViewController实例,而非最初打开文档的那个实例。正确的做法是保留对原始浏览器实例的引用,而非重新初始化。

正确实现步骤

  1. 传递浏览器实例引用:
    在UIDocumentBrowserViewController子类中打开文档时,将自身引用传递给文档视图控制器:
override func documentBrowser(_ controller: UIDocumentBrowserViewController, didPickDocumentsAt documentURLs: [URL]) {
    guard let targetURL = documentURLs.first else { return }
    let docVC = YourDocumentViewController(documentURL: targetURL)
    docVC.documentBrowser = self // 传递原始浏览器实例
    navigationController?.pushViewController(docVC, animated: true)
}
  1. 实现重命名代理逻辑:
    在文档视图控制器中,使用保留的浏览器实例调用重命名API:
class YourDocumentViewController: UIViewController {
    weak var documentBrowser: UIDocumentBrowserViewController?
    var document: UIDocument?
    var currentDocURL: URL?

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.isEditable = true
        navigationItem.renameDelegate = self
        navigationItem.title = currentDocURL?.lastPathComponent
    }
}

extension YourDocumentViewController: UINavigationItemRenameDelegate {
    func navigationItem(_ navigationItem: UINavigationItem, didEndRenamingWith title: String) {
        guard let oldURL = currentDocURL else { return }
        
        documentBrowser?.renameDocument(at: oldURL, proposedName: title) { [weak self] newURL, error in
            guard let self = self else { return }
            
            if let error = error {
                // 重命名失败,恢复原标题
                navigationItem.title = oldURL.lastPathComponent
                print("重命名失败:\(error.localizedDescription)")
                return
            }
            
            // 更新文档URL并重新加载
            self.currentDocURL = newURL
            self.document?.close(completionHandler: { success in
                if success {
                    self.document = UIDocument(fileURL: newURL!)
                    self.document?.open(completionHandler: { _ in
                        // 处理文档重新打开后的逻辑
                    })
                }
            })
        }
    }
}

额外注意事项

  • 重命名操作前确保文档处于已保存状态,避免数据丢失。
  • 重命名成功后,必须更新文档的URL引用并重新打开,原URL将不再指向有效文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 05:34:54