使用UINavigationItemRenameDelegate重命名UIDocument

huangapple go评论81阅读模式
英文:

Renaming UIDocument using UINavigationItemRenameDelegate

问题

我正在尝试通过文档浏览器(UIDocumentBrowserViewController)重命名已打开的 UIDocument

您可以在Apple Pages和Apple Numbers中重命名已打开的文档,它们使用通常的 UINavigationItemRenameDelegate 控件。

这些应用程序是否有特殊权限来执行此操作?似乎您不能使用 NSFileCoordinatorNSFileManager 来实现此操作,因为沙盒书签不允许重命名或移动文件。然而,由Apple开发的应用程序却可以毫无问题地执行此操作。

在我的 Info.plist 中,我有以下设置:

UIFileSharingEnabled: true
LSSupportsOpeningDocumentsInPlace: true

以及以下权限:

com.apple.security.read-write.user-selected: true
com.apple.security.files.user-selected.read-only: true
com.apple.security.files.bookmarks.app-scope: true

UIDocument 的文档中没有提到关于通过 UINavigationItemRenameDelegate 防止重命名文档文件的任何信息。

https://developer.apple.com/documentation/uikit/uidocument

在线上的所有信息似乎都已过时,除了这个手册页面,它并没有真正解决我的问题。Apple的专有应用程序是否使用私有方法/特殊权限来执行此操作,或者我漏掉了什么?

更新于2023年7月5日

2022年的WWDC会议有以下代码片段,根据演讲,您应该使用 UIDocumentBrowserViewController 来重命名文件:

extension ViewController: UINavigationItemRenameDelegate {
    func navigationItem(_ navigationItem: UINavigationItem, didEndRenamingWith title: String) {
        // 尝试重命名我们的文档,完成处理程序将具有更新后的URL或返回错误。
        documentBrowserViewController.renameDocument(at: <#T##URL#>, proposedName: title, completionHandler: <#T##(URL?, Error?) -> Void#>)
    }
}

这更令人困惑。我应该实例化一个新的文档浏览器视图控制器吗?当我这样做时,我会收到以下错误:

ERROR! Error Domain=NSCocoaErrorDomain Code=4099 "The connection from pid 3241 on anonymousListener or serviceListener was invalidated from this process." UserInfo={NSDebugDescription=The connection from pid 3241 on anonymousListener or serviceListener was invalidated from this process.}
[DocumentManager] The view service did terminate with error: Error Domain=_UIViewServiceErrorDomain Code=1 "(null)" UserInfo={Terminated=disconnect method}
[DocumentManager] The UIDocumentBrowserViewController view service crashed for too many times in a row.
[DocumentManager] The view service did terminate with error: Error Domain=_UIViewServiceErrorDomain Code=1 "(null)" UserInfo={Terminated=disconnect method}
英文:

I'm trying to rename UIDocument open via document browser (UIDocumentBrowserViewController).

You can rename open documents in Apple Pages and Apple Numbers, and they use the usual UINavigationItemRenameDelegate controls.

Do these apps have special privileges for doing that? It appears that you can't use NSFileCoordinator or NSFileManager to achieve this, as the sandbox bookmark doesn't allow the file to be renamed or moved. The apps by Apple do this with no issue, though.

In my Info.plist I have:

UIFileSharingEnabled: true
LSSupportsOpeningDocumentsInPlace: true

And the following entitlements:

com.apple.security.read-write.user-selected: true
com.apple.security.files.user-selected.read-only: true
com.apple.security.files.bookmarks.app-scope: true

UIDocument documentation doesn't mention anything about sandboxing preventing renaming document files via UINavigationItemRenameDelegate.

https://developer.apple.com/documentation/uikit/uidocument

All the information online seems antiquated, except for this manual page, which doesn't really clarify my issues. Are the proprietary Apple apps using private methods / special entitlements to do this, or am I missing something here?

Update 2023-07-05:

WWDC session from 2022 has the following code snippet, and according to the talk, you should use UIDocumentWroserViewController to rename files:

extension ViewController: UINavigationItemRenameDelegate {
    func navigationItem(_ navigationItem: UINavigationItem, didEndRenamingWith title: String) {
        // Try renaming our document, the completion handler will have the updated URL or return an error.
        documentBrowserViewController.renameDocument(at: <#T##URL#>, proposedName: title, completionHandler: <#T##(URL?, Error?) -> Void#>)
    }
}

This is even more confusing. Should I instantiate a new document browser view controller? When doing that, I get the following error:

ERROR! Error Domain=NSCocoaErrorDomain Code=4099 "The connection from pid 3241 on anonymousListener or serviceListener was invalidated from this process." UserInfo={NSDebugDescription=The connection from pid 3241 on anonymousListener or serviceListener was invalidated from this process.}
[DocumentManager] The view service did terminate with error: Error Domain=_UIViewServiceErrorDomain Code=1 "(null)" UserInfo={Terminated=disconnect method}
[DocumentManager] The UIDocumentBrowserViewController view service crashed for too many times in a row.
[DocumentManager] The view service did terminate with error: Error Domain=_UIViewServiceErrorDomain Code=1 "(null)" UserInfo={Terminated=disconnect method}

答案1

得分: 0

在大量的试验和错误之后,答案似乎相对简单:

  • 将你的标题栏设置为编辑模式
  • 使你的视图控制器符合UINavigationItemRenameDelegate
  • UIDocumentBrowserViewController添加一个公共变量,在实例化文档视图时,将其连接起来:
let documentViewController = storyBoard.instantiateViewController(withIdentifier: "DocumentViewController") as! MyDocumentViewController
documentViewController.document = MyDocument(fileURL: documentURL)
documentViewController.documentBrowser = self

现在,在你的navigationItem:didEndRenamingWithTitle:方法中,你可以调用文档浏览器来重命名你的文件。

Objective-C:

-(void)navigationItem:(UINavigationItem *)navigationItem didEndRenamingWithTitle:(NSString *)title
{
    [self.documentBrowser renameDocumentAtURL:self.document.fileURL proposedName:title completionHandler:^(NSURL * _Nullable finalURL, NSError * _Nullable error) {
        if (error) {
            self.titleBar.title = self.document.fileURL.lastPathComponent.stringByDeletingPathExtension;
            return;
        }
        
        [self.document presentedItemDidMoveToURL:finalURL];
    }];
}

Swift:

func navigationItem(_ navigationItem: UINavigationItem, didEndRenamingWith title: String) {
    self.documentBrowser.renameDocument(at: self.document.fileURL, to: title) { finalURL, error in
        if let error = error {
            self.titleBar.title = self.document.fileURL.lastPathComponent.deletingPathExtension
            return
        }
        
        self.document.presentedItemDidMove(to: finalURL)
    }
}

苹果真的应该在他们的文档中包含一个最小的示例。

英文:

After tons of trial and error, the answer was somewhat simple:

  • Set up your title bar to editor mode
  • Make your view controller conform to UINavigationItemRenameDelegate
  • Add a public variable for UIDocumentBrowserViewController and when instantiating your document view, hook it up:
let documentViewController = storyBoard.instantiateViewController(withIdentifier: "DocumentViewController") as! MyDocumentViewController
documentViewController.document = MyDocument(fileURL: documentURL)
documentViewController.documentBrowser = self

Now, in your navigationItem:didEndRenamingWithTitle: you can call the document browser to rename your file.

-(void)navigationItem:(UINavigationItem *)navigationItem didEndRenamingWithTitle:(NSString *)title
{
	[self.documentBrowser renameDocumentAtURL:self.document.fileURL proposedName:title completionHandler:^(NSURL * _Nullable finalURL, NSError * _Nullable error) {
		if (error) {
			self.titleBar.title = self.document.fileURL.lastPathComponent.stringByDeletingPathExtension;
			return;
		}
		
		[self.document presentedItemDidMoveToURL:finalURL];
	}];
}

Swift:

func navigationItem(_ navigationItem: UINavigationItem, didEndRenamingWith title: String) {
    self.documentBrowser.renameDocument(at: self.document.fileURL, to: title) { finalURL, error in
        if let error = error {
            self.titleBar.title = self.document.fileURL.lastPathComponent.deletingPathExtension
            return
        }
        
        self.document.presentedItemDidMove(to: finalURL)
    }
}

Apple should really include a minimal example in their documentation.

huangapple
  • 本文由 发表于 2023年6月22日 03:24:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76526523.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定