我有一个 OSX 应用程序,它应该具有用户磁盘中任何位置的文件列表。
应用程序的第一个版本将这些文件的路径保存在核心数据模型中。
但是,如果文件被移动或重命名,该工具就会失去其用途,并且应用程序可能会崩溃。
所以我决定使用书签。它似乎有效,但每次我尝试恢复数据时,我都会得到文件的旧路径。这是为什么?我错过了什么?
我的核心数据实体使用二进制数据字段来保存书签。
书签本身是这样完成的:
NSData * bookmark = [filePath bookmarkDataWithOptions:NSURLBookmarkCreationMinimalBookmark
includingResourceValuesForKeys:NULL
relativeToURL:NULL
error:NULL];
在加载应用程序时,我有一个循环来迭代所有表并恢复书签,如下所示:
while (object = [rowEnumerator nextObject]) {
NSError * error = noErr;
NSURL * bookmark = [NSURL URLByResolvingBookmarkData:[object fileBookmark]
options:NSURLBookmarkResolutionWithoutUI
relativeToURL:NULL
bookmarkDataIsStale:NO
error:&error];
if (error != noErr)
DDLogCError(@"%@", [error description]);
DDLogCInfo(@"File Path: %@", [bookmark fileReferenceURL]);
}
如果我重命名文件,路径为空。我认为存储此 NSData 对象和带有路径的字符串没有区别。所以我显然错过了一些东西。
编辑: 我也经常遇到这样的错误:
CFURLSetTemporaryResourcePropertyForKey failed because it was passed this URL which has no scheme
。
我感谢任何帮助,谢谢!
我在代码中找不到任何问题,所以我更改了它。
在查找“无方案”消息的原因后,我得出的结论是,此代码需要一些第三方应用程序才能工作,这是不可取的。
我现在使用别名。这就是我创建它们的方式:
FSRef fsFile, fsOriginal;
AliasHandle aliasHandle;
NSString * fileOriginalPath = [[filePath absoluteString] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
OSStatus status = FSPathMakeRef((unsigned char*)[fileOriginalPath cStringUsingEncoding: NSUTF8StringEncoding], &fsOriginal, NULL);
status = FSPathMakeRef((unsigned char*)[fileOriginalPath cStringUsingEncoding: NSUTF8StringEncoding], &fsFile, NULL);
OSErr err = FSNewAlias(&fsOriginal, &fsFile, &aliasHandle);
NSData * aliasData = [NSData dataWithBytes: *aliasHandle length: GetAliasSize(aliasHandle)];
现在我像这样恢复路径:
while (object = [rowEnumerator nextObject]) {
NSData * aliasData = [object fileBookmark];
NSUInteger aliasLen = [aliasData length];
if (aliasLen > 0) {
FSRef fsFile, fsOriginal;
AliasHandle aliasHandle;
OSErr err = PtrToHand([aliasData bytes], (Handle*)&aliasHandle, aliasLen);
Boolean changed;
err = FSResolveAlias(&fsOriginal, aliasHandle, &fsFile, &changed);
if (err == noErr) {
char pathC[2*1024];
OSStatus status = FSRefMakePath(&fsFile, (UInt8*) &pathC, sizeof(pathC));
NSAssert(status == 0, @"FSRefMakePath failed");
NSLog(@"%@", [NSString stringWithCString: pathC encoding: NSUTF8StringEncoding]);
} else {
NSLog(@"The file disappeared!");
}
} else {
NSLog(@"CardCollectionUserDefault was zero length");
}
}
但是,我仍然很好奇为什么我之前的代码失败了。我很欣赏对此的任何想法。谢谢!
我成功使用了
NSError *err = nil;
NSURL *url = [NSURL fileURLWithPath:path];
NSData *bookmarkData = [url bookmarkDataWithOptions:NSURLBookmarkCreationSuitableForBookmarkFile includingResourceValuesForKeys:nil relativeToURL:nil error:&err];
然后,即使您移动或重命名文件,bookmarkData 也会正确检索其当前路径
BOOL isStale;
NSURL *urlOut = [NSURL URLByResolvingBookmarkData:bookmarkData options:NSURLBookmarkResolutionWithoutUI relativeToURL:nil bookmarkDataIsStale:&isStale error:&err];
NSString *path = urlOut.path;