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}
After tons of trial and error, the answer was somewhat simple:
UINavigationItemRenameDelegate
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.