英文:
Renaming UIDocument using UINavigationItemRenameDelegate
问题
我正在尝试通过文档浏览器(UIDocumentBrowserViewController
)重命名已打开的 UIDocument
。
您可以在Apple Pages和Apple Numbers中重命名已打开的文档,它们使用通常的 UINavigationItemRenameDelegate
控件。
这些应用程序是否有特殊权限来执行此操作?似乎您不能使用 NSFileCoordinator
或 NSFileManager
来实现此操作,因为沙盒书签不允许重命名或移动文件。然而,由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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论