为什么NSURL的NSURLDocumentIdentifierKey(几乎)总是为零?

时间:2015-04-20 16:06:40

标签: objective-c macos cocoa filesystems osx-yosemite

OSX Yosemite在NSURL上引入了一个非常方便的属性:NSURLDocumentIdentifierKey

从文档中引用:

  

NSURLDocumentIdentifierKey

     

作为NSNumber(只读)返回的文档标识符。   文档标识符是内核分配给文件或目录的值。此值用于标识文档,无论文档在卷上的位置如何。标识符在系统重新启动后仍然存在。复制文件时不会传输它,但它会在“安全保存”操作中继续存在。例如,即使在调用replaceItemAtURL后,它仍保留在分配给它的路径上:withItemAtURL:backupItemName:options:resulItemURL:error:method 。文档标识符在单个卷中是唯一的。所有卷都不支持此属性。

     

在OS X v10.10和iOS 8.0中可用。

不幸的是,这个值似乎大多为零(除了罕见的例子,看起来彼此完全断开)。

特别是,此代码将在最后一行抛出异常(在Yosemite 10.10.3上测试):

    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSArray *attributesFlags = @[NSURLNameKey, mNSURLDocumentIdentifierKey];

    NSDirectoryEnumerator *en = [fileManager enumeratorAtURL:[NSURL URLWithString:NSHomeDirectory()]
                                  includingPropertiesForKeys:attributesFlags
                                                     options:NSDirectoryEnumerationSkipsHiddenFiles
                                                errorHandler:^BOOL(NSURL *url, NSError *error) {
                                                    NSAssert(NO, @"An error has occured");
                                                    return YES;
                                                 }];

    for(NSURL *URL in en) {
        NSNumber *documentID = nil;
        NSError *error = nil;
        BOOL result = [URL getResourceValue:&documentID forKey:NSURLDocumentIdentifierKey error:&error]; \
        NSAssert(result == YES && error==nil, @"Unable to read property. Error: %@", error); \
        NSLog(@"Processing file: %@", URL);


        // This will break most of the times
        NSAssert(documentID != nil, @"Document ID should not be nil!!");
    }

也许我误解了文档,但在我看来NSURLDocumentIdentifierKey应该可以在磁盘上的每个文件中使用。

3 个答案:

答案 0 :(得分:2)

我在这个问题上向Apple提交了一个错误,并对我的报告得到了反馈。截至今天,跟踪DocumentIdentifier的信息尚未成为文档的一部分,但机票仍然是开放的。

缺少的信息是文件系统默认不跟踪DocumentIdentifier。您必须通过使用带有chflags标记的UF_TRACKED在要跟踪的每个文件上设置标记来启用跟踪。

以下脚本将打印文件的DocumentIdentifier

https://gist.github.com/cmittendorf/fac92272a941a9cc64d5

此脚本将启用跟踪DocumentIdentifier

https://gist.github.com/cmittendorf/b680d1a03aefa08583d7

答案 1 :(得分:0)

显然,Yosemite只有在知道某些内容正在尝试跟踪其身份(例如Versions或iCloud)时才会将 DocumentIdentifier 分配给文件。

我没有看到任何与内核交谈的方式,并告诉它开始跟踪你感兴趣的文件。我希望在将来的版本中发生这种变化,因为API已经在OS X 10.10上公开了,而且此时它几乎没用。

答案 2 :(得分:0)

macOS 10.14中仍然存在此问题。它可能不会改变。

解决方法是从NSFileManager获取索引节点,如下所示:

NSFileManager *fmgr = [NSFileManager defaultManager];
NSDictionary *attributes = [fmgr attributesOfItemAtPath:url.path error:nil;
if (attributes != nil) {
    NSNumber *inode = [attributes objectForKey:NSFileSystemFileNumber];
    ...
}