UIDocument打开/关闭行为

时间:2012-06-25 06:32:18

标签: ios objective-c icloud uidocument

我有一个基于UIDocument的应用程序,没有iCloud支持。用户可以创建文档,并将其保存到应用程序的文档目录。

我还创建了一些“示例”文档,并使用应用程序包传递它们。我希望用户能够以打开自己的文档的方式打开示例文档:

NSArray *samplesContent = [[NSBundle mainBundle] URLsForResourcesWithExtension:@"doco" subdirectory:@"Samples"];

for (NSURL *sampleURL in samplesContent) {
    Doco *doco = [[Doco alloc] initWithFileURL:sampleURL];
    [doco disableEditing];

    [doco openWithCompletionHandler:^(BOOL success) {
        if (success) {
            [self.docos addObject:doco];

            if (self.docos.count >= samplesContent.count) {
                [self.tableView reloadData];
            }
        } else DLog(@"Failed to open %@", [sampleURL pathExtension]);
     }];
}

我所看到的是:

  1. viewDidLoad上,docs数组会填充示例文档,并在第一次启动应用时显示在tableView中。这里没有问题,一切都很顺利。
  2. 然后我退出视图,使用以下代码关闭所有打开的文档:

    int count = 0;
    
    for (Doco *doco in self.docos) {
        if (doco.documentState == UIDocumentStateNormal) {
            [doco closeWithCompletionHandler:nil];
            count++;
        }
    }
    
    DLog(@"Closed %i docs", count);
    
  3. 当我再次打开视图时,应该再次填充文档数组并重新填充tableView,但没有任何反应。

  4. 下面的完成处理程序永远不会被调用,尽管URL指向同一个文件并且它是有效的:

    [doco openWithCompletionHandler:^(BOOL success) {}
    

    对于存储在Documents中的用户生成的文档,我没有这个问题,所以我的假设是它与自动保存有关,在只读包上调用并失败

    但我有点困在这一部分,任何帮助都将受到赞赏。

2 个答案:

答案 0 :(得分:2)

如果更新了UIDocument,它将尝试在关闭时保存更改。 由于UIDocument是从只读包中加载的,因此我必须确保它不会更新,否则close block返回success=NO,文档未关闭...

答案 1 :(得分:2)

问题已经确定,但我认为值得描述一些简单的解决方案,因为在应用程序包中包含示例文档并不罕见。

所以问题是示例文档在关闭时试图保存更改,但在只读应用程序包中保存不会成功。

我认为这里有两个主要的解决方案:

  1. 将示例文档复制到Documents目录中,可以将其视为任何其他文档并成功保存(如果您希望保存用户对样本文档的编辑,请使用此方法)。

  2. 防止文档尝试保存(对于只读示例文档)。

  3. 所以这里有一些简单的例子......


    1。将样本文档复制到Documents目录

    首次发布时(或者当您决定刷新示例文档时),使用NSFileManager将文件复制到位:

    - (void)refreshSampleDocuments
    {
        NSArray *sampleFromURLs = [[NSBundle mainBundle] URLsForResourcesWithExtension:@"doc" subdirectory:@"Samples"];
    
        for (NSURL *sampleFromURL in sampleFromURLs) {
    
            NSString *sampleFilename = [sampleFromURL lastPathComponent];
            NSURL *sampleToURL = [[self documentsDirectoryURL] URLByAppendingPathComponent:sampleFilename];
    
            // ...
            // Do some checks to make sure you won't write over any user documents!
            // ....
    
            NSError *error;
            BOOL copySuccessful = [[NSFileManager defaultManager] copyItemAtURL:sampleFromURL toURL:sampleToURL error:&error];
    
            if (!copySuccessful) {
                // Handle error...
            }
        }
    }
    

    2。防止样本文档尝试保存

    这种方法更简单(对于只读文档),并且比在文档中可能出现的任何地方都更容易防​​止更新。

    closeWithCompletionHandler:上调用UIDocument时,会调用autosaveWithCompletionHandler:以确保在关闭之前保存文档文件。这反过来调用hasUnsavedChanges来决定是否需要保存。因此,如果hasUnsavedChanges返回NO,那么对自动保存机制的任何调用将导致不会写出任何更改。

    (N.B。手动调用saveToURL:forSaveOperation:completionHandler:仍会强行保存,无论hasUnsavedChanges返回什么内容。)

    因此,在UIDocument子类中,如果文档是只读的,请覆盖hasUnsavedChanges以返回NO

    @interface MyDocument : UIDocument
    
    @property(nonatomic, getter = isReadOnly) BOOL readOnly;
    
    @end
    
    
    @implementation MyDocument
    
    - (BOOL)hasUnsavedChanges
    {
        return [self isReadOnly] ? NO : [super hasUnsavedChanges];
    }
    
    @end