Macos NSFileWrapper有时返回nil
我正在为我的包文档使用Macos NSFileWrapper有时返回nil,macos,cocoa,nsdocument,nsfilewrapper,Macos,Cocoa,Nsdocument,Nsfilewrapper,我正在为我的包文档使用NSFileWrapper。有时,当我请求包中文件的数据时,我会得到nil 以下是我如何查询包中文件的数据: - (NSData*) dataOfFile(NSString*)filename { NSFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename]; return fileWrapper.regularFileContents;
NSFileWrapper
。有时,当我请求包中文件的数据时,我会得到nil
以下是我如何查询包中文件的数据:
- (NSData*) dataOfFile(NSString*)filename {
NSFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
return fileWrapper.regularFileContents; // This returns nil sometimes. Why?
}
- (BOOL) readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
self.documentFileWrapper = fileWrapper;
return YES;
}
- (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];
}
- (NSFileWrapper*) fileWrapperOfType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
return self.documentFileWrapper;
}
对于某些文件(不是所有文件),此方法最终开始返回nil。可悲的是,我没有成功地重现问题的始终如一
如果有帮助,以下是我打开软件包的方式:
- (NSData*) dataOfFile(NSString*)filename {
NSFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
return fileWrapper.regularFileContents; // This returns nil sometimes. Why?
}
- (BOOL) readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
self.documentFileWrapper = fileWrapper;
return YES;
}
- (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];
}
- (NSFileWrapper*) fileWrapperOfType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
return self.documentFileWrapper;
}
这是我更新包内文件数据的方式:
- (NSData*) dataOfFile(NSString*)filename {
NSFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
return fileWrapper.regularFileContents; // This returns nil sometimes. Why?
}
- (BOOL) readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
self.documentFileWrapper = fileWrapper;
return YES;
}
- (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];
}
- (NSFileWrapper*) fileWrapperOfType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
return self.documentFileWrapper;
}
以下是我保存软件包的方式:
- (NSData*) dataOfFile(NSString*)filename {
NSFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
return fileWrapper.regularFileContents; // This returns nil sometimes. Why?
}
- (BOOL) readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
self.documentFileWrapper = fileWrapper;
return YES;
}
- (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];
}
- (NSFileWrapper*) fileWrapperOfType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
return self.documentFileWrapper;
}
为什么会发生这种情况?有什么办法可以预防吗
的文档似乎讨论了此问题:
如果用户在修改后修改了文件,此方法可能会返回nil
调用readFromURL:options:error:或initWithURL:options:error:but
在NSFileWrapper读取文件内容之前。使用
NSFileWrapperReading立即读取选项以降低可能性
这个问题的答案
但是我不明白为了防止这种情况,上面的代码中需要做哪些更改
失败的实验
如果regularFileContents
returnnil,我尝试保存文档,但之后它仍然返回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;
}
没有足够的代码来查看实际情况。然而,根本原因是
NSFileWrapper
正是其名称所暗示的:一个表示文件或目录的对象。因此,实际文件或目录很容易与内存中的对象“不同步”。无论何时NSFileWrapper
确定发生了这种情况,它都会为某些操作返回nil。解决方案是使NSFileWrapper
对象短命。在需要时创建并打开它们,然后尽快保存并关闭
特别是,您的代码似乎将指向包目录包装器的指针保留了很长一段时间,并假设它始终有效。如果目录因任何原因发生更改,则情况并非如此。重新编码,以便每次需要时都能得到一个新的包目录包装器,问题应该会消失。如果文件在磁盘上发生更改,那么您将得到零(正如@Gene所说)。但是,您可以使用
matchesContentsOfURL:
方法检查这一点,该方法:
根据上次读取或写入文件时存储的文件属性,确定磁盘表示形式是否已更改。如果文件包装器的修改时间或访问权限不同于磁盘上文件的修改时间或访问权限,则此方法返回YES。然后可以使用readFromURL:options:error:
这来自苹果的文档
请注意该部分的简介:
因为文件包装的目的是表示内存中的文件,所以它与任何磁盘表示都是松散耦合的。文件包装器不会记录其内容的磁盘表示形式的路径。这允许您使用不同的URL保存相同的文件包装器,但如果您希望稍后从磁盘更新文件包装器,还需要记录这些URL
因此,如果您想/需要重新读取,您必须将url保存到原始文件
当您看到无结果时,
matchesContentsofURL:
返回的内容很有趣。这是一个疯狂的猜测,但我想知道spotlight是否在保存后修改了文件属性(比如重新索引文件或其他)?我有点好奇,为什么你在失败后还要存钱;为什么不重新打开它呢?只是猜测,尝试给你一些想法。疯狂的猜测,但我认为你的对象被释放了。也许alloc出了问题。你试过分析吗?小心alloc&init(和self.+自动释放和释放)。