【问题标题】:UIDocument, NSFileWrapper and ImagesUIDocument、NSFileWrapper 和图像
【发布时间】:2012-06-14 13:58:33
【问题描述】:

我有一个 UIDocument,我希望它由 (1) 一个 txt 文件和 (2) 几个 jpg 图像组成。我把 txt 和所有的 jpgs 放到一个 NSFileWrapper 中。

当我加载 UIDocument 时,我很快就需要 txt 文件中的信息,所以我先加载它并忽略所有图像,直到我真正需要它们。

虽然我知道如何延迟加载图像,但我不确定如何“延迟”保存图像(尤其是在使用 iCloud 时,我不希望文件被不必要地上传/下载)。假设我已经加载了所有图像并且没有更改它们。然后我想保存 UIDocument,忽略所有图像(因为它们没有改变)但想保存文本,因为它确实改变了。

我将如何实现这一目标?甚至可能吗?还是自动完成?还是我应该不将图像放在我的 UIDocument 中,让每个图像由不同的 UIDocument 处理? 恐怕这对我来说有点混乱。

到目前为止,这是我的代码,它将保存所有图像和文本(无论它们是否被更改):


UIDocument

-(id)contentsForType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {

        NSMutableDictionary *wrappers = [NSMutableDictionary dictionary];
// the following puts a wrapper into a dictionary of wrappers:
        [self encodeObject:self.text toWrappers:wrappers toFileName:@"text.data"];
        [self encodeObject:self.photos toWrappers:wrappers toFileName:@"photos.data"];
        NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:wrappers];

        return fileWrapper;

    }

当我要保存 UIDocument 时:

[self.doc saveToURL:self.doc.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) {
    [self.doc closeWithCompletionHandler:^(BOOL success) {}];
}];

【问题讨论】:

  • 我的诚实意见(虽然没有使用 iCloud,但已从设备上的文件系统完成此操作)创建了一个文件,其中文本文件包括显示文本,以及告诉我的基于文本的元标记在哪里获取图像。这样我可以延迟加载每个文件,或者延迟保存每个文件。现在,另一方面,这并没有做的是保留您可能希望维护的原子写入(保持您的图像与保存在您保存到的任何设备上的文本文件对齐)。
  • 一个问题可能是,当用户告诉你保存他们的数据时,你为什么要“懒惰地”保存它的任何部分?为什么不在此时将其存储到服务器(iCloud)或在 iCloud 不可用时将其本地存储并在 iCloud 可用时推送到服务器进行同步?此时将用户的数据保存为最高优先级!
  • 我本质上是在建议不同的 UIDocuments,一个是你的文本文件,另一个是图像文件。在文本文件中,它会告诉您去哪里获取图像文件。
  • 一如既往,答案是“视情况而定”。真的归结为您宁愿懒惰地保存还是进行原子写入?
  • 在对该主题进行了更多阅读之后,似乎 UIDocument 实际上确实考虑了原子文件操作(或者正如他们所说的“安全”)。也直接取自 Apple 在 NSFileWrapper 上的网站 - “文件包装器支持增量保存。与单个二进制数据对象相比,如果文件包装器包含您的文档数据(例如,文本和图像)并且文本发生更改,则只有必须将包含文本的文件写入磁盘。此功能可提高性能。”它应该支持你想要的阅读和写作。

标签: iphone cocoa-touch icloud uidocument nsfilewrapper


【解决方案1】:

您应该在 UIDocument 实例中保留对 NSFileWrapper 的引用。这样,只有更改的内容会被重写,而不是整个包装器。

因此,在加载文件(或为新文档创建新文件)时保留参考:

- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outError {
    // save wrapper:
    self.fileWrapper = (NSFileWrapper*)contents;

现在您只需在文件实际更改时更新包装器:

- (id)contentsForType:(NSString *)typeName error:(NSError **)outError {
    NSFileWrapper *subwrapper = [self.fileWrapper.wrappers objectForKey:@"subwrapper"];
    if(self.somethingChanged) {
        [self.fileWrapper.wrappers removeFileWrapper:subwrapper];
        subwrapper = [[NSFileWrapper alloc] initRegularFileWithContents:…

我知道代码非常简短,但我希望这有助于为您指明正确的方向。

【讨论】:

    猜你喜欢
    • 2014-06-09
    • 1970-01-01
    • 2013-02-20
    • 1970-01-01
    • 2013-02-20
    • 1970-01-01
    • 2016-11-18
    • 2018-08-17
    • 2013-10-14
    相关资源
    最近更新 更多