将 UIDocument 移动到文件系统上的新位置的正确方法是什么

发布于 2024-12-18 08:26:23 字数 148 浏览 7 评论 0原文

我有一个基于文档的 iOS 应用程序,带有 UIDocument 子类。我需要能够移动它在文件系统上代表的文件。我考虑过用 NSFileManager 移动它,但这会弄乱 UIDocument 的 fileURL 属性。关于如何解决这个小难题有什么想法吗?

I have a document-based iOS application with a UIDocument subclass. I need to be able to move the file it represents on the file-system. I have considered moving it with an NSFileManager, but this would mess up the UIDocument's fileURL property. Any ideas on how to solve this little conundrum?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

安人多梦 2024-12-25 08:26:23

这可能很旧但仍然相关。

您想要执行的操作如下:

对于移动:使用 NSFileCoordinator 移动文件,在协调器的块内,调用

[fileCoordinator itemAtURL:URL willMoveToURL:toURL];
[fileManager moveItemAtURL:newURL toURL:toURL error:&moveError];
[fileCoordinator itemAtURL:URL didMoveToURL:toURL];

对于删除:覆盖您的 UIDocument 子类或实现文件呈现器协议方法 accommodatePresentedItemDeletionWithCompletionHandler: 来关闭文档。

- (void)accommodatePresentedItemDeletionWithCompletionHandler:(void (^)(NSError *))completionHandler;
{
[self closeWithCompletionHandler:^(BOOL success) {
    NSError *err;
    if (!success)
        err = [NSError error]; // implement your error here if you want

    completionHandler(err);
}];
}

从而确保它能够正确处理移动。

This might be old but still relevant.

What you want to do is the following:

For moving: move your file using NSFileCoordinator, inside the coordinator's block, call

[fileCoordinator itemAtURL:URL willMoveToURL:toURL];
[fileManager moveItemAtURL:newURL toURL:toURL error:&moveError];
[fileCoordinator itemAtURL:URL didMoveToURL:toURL];

For deleting: overwrite your UIDocument subclass or implement the file presenter protocol method accommodatePresentedItemDeletionWithCompletionHandler: to close the document.

- (void)accommodatePresentedItemDeletionWithCompletionHandler:(void (^)(NSError *))completionHandler;
{
[self closeWithCompletionHandler:^(BOOL success) {
    NSError *err;
    if (!success)
        err = [NSError error]; // implement your error here if you want

    completionHandler(err);
}];
}

Thus ensuring it will correctly handle being moved.

玩世 2024-12-25 08:26:23

您可以通过首先关闭 UIDocument,然后在完成处理程序中使用 NSFileManager 移动文件来重命名它。成功移动文件后,使用新文件 URL 初始化 UIDocument 子类的新实例:

NSURL *directoryURL = [_document.fileURL URLByDeletingLastPathComponent];    
NSFileManager *fileManager = [[NSFileManager alloc] init];    
NSString *filePath = [directoryURL.path stringByAppendingPathComponent:@"NewFileName"];

[_document closeWithCompletionHandler:^(BOOL success) {
    NSError *error;

    if (success)
        success = [fileManager moveItemAtPath:_document.fileURL.path toPath:filePath error:&error];

    if (success) {
        NSURL *url = [NSURL fileURLWithPath:filePath];

        // I handle opening the document and updating the UI in setDocument:
        self.document = [[MyDocumentSubclass alloc] initWithFileName:[url lastPathComponent] dateModified:[NSDate date] andURL:url];
    } else {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"Unable to rename document" delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil];
        [alert show];
        NSLog(@"Unable to move document: %@", error);
    }
}];

You can rename a UIDocument by first closing it, and then in the completion handler, moving the file using NSFileManager. Once the file has been successfully moved, initialize a new instance of your UIDocument subclass using the new file URL:

NSURL *directoryURL = [_document.fileURL URLByDeletingLastPathComponent];    
NSFileManager *fileManager = [[NSFileManager alloc] init];    
NSString *filePath = [directoryURL.path stringByAppendingPathComponent:@"NewFileName"];

[_document closeWithCompletionHandler:^(BOOL success) {
    NSError *error;

    if (success)
        success = [fileManager moveItemAtPath:_document.fileURL.path toPath:filePath error:&error];

    if (success) {
        NSURL *url = [NSURL fileURLWithPath:filePath];

        // I handle opening the document and updating the UI in setDocument:
        self.document = [[MyDocumentSubclass alloc] initWithFileName:[url lastPathComponent] dateModified:[NSDate date] andURL:url];
    } else {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"Unable to rename document" delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil];
        [alert show];
        NSLog(@"Unable to move document: %@", error);
    }
}];
怂人 2024-12-25 08:26:23

我在 UIDocument 类规范 (5.1) 中找到了这一点:

NSFilePresenter协议的实现

UIDocument 类采用 NSFilePresenter 协议。当另一个客户端尝试读取基于 UIDocument 的应用程序的文档时,该读取会暂停,直到 UIDocument 对象有机会保存对文档所做的任何更改。

尽管某些实现不执行任何操作,但 UIDocument 实现了所有 NSFilePresenter 方法。具体来说,UIDocument

<块引用>

实现relinquishPresentedItemToReader:以将传入块转发到performAsynchronousFileAccessUsingBlock:

实现relinquishPresentedItemToWriter:来检查文件修改日期是否已更改;如果文件比以前新,它会调用 revertToContentsOfURL:completionHandler:,并将 fileURL 的值作为 URL 参数。

实现 presentedItemDidMoveToURL: 以更新文档的文件 URL (fileURL)。

在您的 UIDocument 子类中,如果您重写 NSFilePresenter 方法,您始终可以调用超类实现 (super)。

我也在绝望地寻找,希望以上内容有所帮助。我还没有测试过——我现在就开始尝试。

所以基本上,如果我没有错过这里的任何内容,您必须使用 NSFileManager 移动文档,然后在文档上调用 presentedItemDidMoveToURL: 。您可能必须使用 NSFileCoordinator 移动文件,以确保不会出现问题。

请纠正这个答案中所有错误的地方。在所有这些事情上我仍然是一个n00b

I found this in the UIDocument class specification (5.1):

Implementation of NSFilePresenter Protocol

The UIDocument class adopts the NSFilePresenter protocol. When another client attempts to read the document of a UIDocument-based application, that reading is suspended until the UIDocument object is given an opportunity to save any changes made to the document.

Although some implementations do nothing, UIDocument implements all NSFilePresenter methods. Specifically, UIDocument:

Implements relinquishPresentedItemToReader: to forward the incoming block to performAsynchronousFileAccessUsingBlock:.

Implements relinquishPresentedItemToWriter: to check if the file-modification date has changed; if the file is newer than before, it calls revertToContentsOfURL:completionHandler: with the value of the fileURL as the URL parameter.

Implements presentedItemDidMoveToURL: to update the document’s file URL (fileURL).

In your UIDocument subclass, if you override a NSFilePresenter method you can always invoke the superclass implementation (super).

I was hopelessly searching too and I hope the above helps. I haven't tested it yet — I'm jumping on it right now.

So basically, if I don't miss anything here, you have to move the document using NSFileManager and then call presentedItemDidMoveToURL: on your document. You have probably to move the file using NSFileCoordinator, to make sure you don't get problems.

Please correct everything in this answer that's wrong. I'm still a n00b in all that stuff.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文