cocoa - 基于 NSDocument 的 Mac 应用程序,带有文档 bundle ,保存速度超慢

标签 cocoa bundle nsdocument

所以在谷歌搜索了一下之后,我的理解是,当我在基于 NSDocument 的应用程序中使用文档包时,我每次想要保存时都必须编写整个包?当我向文档中添加大型视频文件时,这开始出现问题。

有什么办法可以解决这个问题而不抛出 NSDocument 吗?

最佳答案

使用文档包的优点之一是您无需在每次保存时都写入所有内容。您应该将 documentFileWrapper 属性添加到您的 NSDocument 子类中,并且当文档架构读取文档包时,您应该将 NSFileWrapper 引用存储在该属性,您还应该跟踪已更改的内容。例如,a假设您在文档包中保存一个文本文件和一个视频文件:

@interface MyDocument ()
    @property (nonatomic, copy) NSString *text;
    @property (nonatomic, assign) bool textHasChanged;

    @property (nonatomic, copy) NSData *videoData;
    @property (nonatomic, assign) bool videoHasChanged;

    @property (nonatomic, strong) NSFileWrapper *documentFileWrapper;
@end

- (BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper
                     ofType:(NSString *)typeName
                      error:(NSError **)outError {


    // Read the contents of file wrapper
    // …

    [self setDocumentFileWrapper:fileWrapper];

    return YES;
}

如果从磁盘读取文档包,documentFileWrapper 会保留对该包的引用。如果是新文档,则 documentFileWrappernil

保存文档时,您可以重用documentFileWrapper并仅写入需要保存的文件。如果文档尚未保存(它是一个新文档),则 documentFileWrappernil,因此您需要创建一个:

- (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName
                               error:(NSError **)outError
{

    if ([self documentFileWrapper] == nil) {
        NSFileWrapper *documentFileWrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:@{}];
        [self setDocumentFileWrapper:documentFileWrapper];
    }

    NSDictionary *fileWrappers = [[self documentFileWrapper] fileWrappers];
    NSFileWrapper *textFileWrapper = [fileWrappers objectForKey:@"text.txt"];
    NSFileWrapper *videoFileWrapper = [fileWrappers objectForKey:@"video.mp4"];

    if ((textFileWrapper == nil && [self text] != nil) || [self textHasChanged]) {
        if (textFileWrapper != nil)
            [documentFileWrapper removeFileWrapper:textFileWrapper];

        if ([self text] != nil) {
            NSData *textData = [[self text] dataUsingEncoding:NSUTF8StringEncoding];
            [documentFileWrapper addRegularFileWithContents:textData preferredFileName:@"text.txt"];
        }
    }

    if ((videoFileWrapper == nil && [self videoData] != nil) || [self videoHasChanged]) {
        if (videoFileWrapper != nil)
            [documentFileWrapper removeFileWrapper:videoFileWrapper];

        if ([self videoData] != nil)
            [documentFileWrapper addRegularFileWithContents:[self videoData] preferredFileName:@"video.mp4"];
    }

    return documentFileWrapper;
}

在上面的代码中,仅当文档包(文件包装器)尚不存在时才会创建它。换句话说,仅当文档是新的且尚未保存时才会创建它。创建包后,其引用存储在 documentFileWrapper 中。

接下来,我们检查是否需要写入文本文件。如果满足以下条件,则可写为: * 要么还没有文本文件(可能是因为它是一个新包)并且我们有实际的文本要写入; * 或者如果文本已更改。

我们对视频文件执行相同的操作。

请注意,如果文档已从磁盘加载或保存至少一次,则仅当视频数据已被加载时,视频文件才会添加到包中(并且之前的视频文件(如果有)将从包中删除)。改变了。

注意:这个答案假设 ARC 和自动属性合成(ivar 名称以下划线前缀)。

关于cocoa - 基于 NSDocument 的 Mac 应用程序,带有文档 bundle ,保存速度超慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16773343/

相关文章:

cocoa - 如何在 Mac OS X 的 Cocoa 上绘制文本内阴影

Mercurial:强制分拆具有未知父项的 bundle

objective-c - NSDocumentController currentDocument 返回 nil

objective-c - cocoa 自定义NSDocument保存

objective-c - 基于 NSDocument 的应用程序,启动时使用 'New Document' 按钮打开对话框

cocoa - OSX/Cocoa 应用程序通常使用什么位置来存储数据文件?

objective-c - 使用 NSDocument 打开任何文件夹

jquery - 刚开始 mvc 4 我可以在哪里调整包

cocoa - launchd 守护进程的安全密码存储

angular - 使用 UMD bundle bundle Angular 2 应用程序(不构建 vendor bundle )