【问题标题】:Why is NSURL's NSURLDocumentIdentifierKey (almost) always nil?为什么 NSURL NSURL DocumentIdentifierKey (几乎)总是为零?
【发布时间】:2019-05-03 20:19:27
【问题描述】:

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

引用文档:

NSURLDocumentIdentifierKey

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

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

不幸的是,该值似乎大部分为 nil(除了极少数的例子,它们之间似乎完全断开)。

特别是,此代码将在最后一行抛出异常(在 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 应该在磁盘上的每个文件上都可用。

【问题讨论】:

  • 这里是否涉及沙盒?
  • 我不这么认为:我根本没有使用沙盒。除非这是 MAS 独有的功能,但我不这么认为。

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


【解决方案1】:

我就这个问题向 Apple 提交了一个错误,并收到了关于我的报告的反馈。截至今天,有关跟踪 DocumentIdentifier 的信息尚未包含在文档中,但票证仍处于开放状态。

缺少的信息是,文件系统默认不跟踪DocumentIdentifier。您必须通过使用chflagsUF_TRACKED 标志在要跟踪的每个文件上设置一个标志来启用跟踪。

以下脚本将打印文件的DocumentIdentifier

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

此脚本将启用跟踪DocumentIdentifier

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

【讨论】:

  • 我想知道如果对大量文件启用此功能会对性能产生什么影响。
  • 非常有趣。我也想知道对性能有什么影响。如果它适用于网络文件系统。
【解决方案2】:

显然,只有当 Yosemite 知道某些东西正在尝试跟踪其身份(如版本或 iCloud)时,它才会将 DocumentIdentifier 分配给文件。

我看不到任何与内核对话并告诉它开始跟踪您感兴趣的文件的方法。我希望这会在未来的版本中有所改变,因为该 API 已在 OS X 10.10 上公开,此时它几乎没有用处。

【讨论】:

    【解决方案3】:

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

    解决方法是从NSFileManager 获取inode,如下所示:

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

    【讨论】:

      猜你喜欢
      • 2016-02-14
      • 1970-01-01
      • 2015-09-02
      • 1970-01-01
      • 2016-11-24
      • 2012-03-12
      • 1970-01-01
      • 2012-04-05
      • 1970-01-01
      相关资源
      最近更新 更多