NSFileWrapper有时会返回nil

hpi*_*que 9 macos cocoa nsdocument nsfilewrapper

我正在使用NSFileWrapper我的包文件.有时,当我请求包中的文件数据时,我得到了nil.

这是我查询包内文件数据的方法:

- (NSData*) dataOfFile(NSString*)filename {
    NSFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
    return fileWrapper.regularFileContents; // This returns nil sometimes. Why?
}
Run Code Online (Sandbox Code Playgroud)

对于某些文件(并非所有文件),此方法最终开始返回nil.可悲的是,我没有设法一致地重现这个问题.

如果它有帮助,这就是我打开包的方式:

- (BOOL) readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
    self.documentFileWrapper = fileWrapper;
    return YES;
}
Run Code Online (Sandbox Code Playgroud)

这是我更新包内文件数据的方法:

- (void) updateFile:(NSString*)filename withData:(NSData*)data {
    SBFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
    if (fileWrapper) {
        [self.documentFileWrapper removeFileWrapper:fileWrapper];
    }
    NSFileWrapper *fileWrapper = [[SBFileWrapper alloc] initRegularFileWithContents:data ];
    fileWrapper.preferredFilename = filename;
    [self.documentFileWrapper addFileWrapper:fileWrapper];
}
Run Code Online (Sandbox Code Playgroud)

这是我保存包的方式:

- (NSFileWrapper*) fileWrapperOfType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
    return self.documentFileWrapper;
}
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况?有没有办法防止它?

文档regularFileContents似乎谈论这个问题:

如果用户在调用readFromURL后修改文件,则此方法可能返回nil:options:error:或initWithURL:options:error:但在NSFileWrapper读取文件内容之前.使用NSFileWrapperReadingImmediate读取选项可以降低该问题的可能性.

但我不明白上面的代码中有什么必须改变以防止这种情况.

实验失败

如果regularFileContents返回nil 我尝试保存文档,但之后仍然返回nil.像这样:

- (NSData*) dataOfFile(NSString*)filename {
    NSFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
    NSData *data = fileWrapper.regularFileContents;
    if (!data) {
            [self saveDocument:nil];
            fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
            data = fileWrapper.regularFileContents;
    }
    return data;
}
Run Code Online (Sandbox Code Playgroud)

Gen*_*ene 4

没有足够的代码来了解到底发生了什么。然而,根本原因正如其名称所暗示的那样:代表文件或目录的NSFileWrapper对象。因此,实际文件或目录很容易与内存中的对象“不同步”。每当确定发生这种情况时,它都会对某些操作返回 nil。解决方案是让对象变得短暂。在需要时创建并打开它们,然后尽快保存并关闭。 NSFileWrapperNSFileWrapper

特别是,您的代码似乎长时间保留了指向包目录包装器的指针,并假设它始终有效。如果目录因任何原因发生更改,则情况并非如此。重新编码,以便每次需要时都获得一个新的包目录包装器,并且问题应该消失。