【问题标题】:iCloud NSMetadataQuery and updates (NSMetadataQueryUpdateChangedItemsKey)iCloud NSMetadataQuery 和更新 (NSMetadataQueryUpdateChangedItemsKey)
【发布时间】:2015-11-17 15:13:33
【问题描述】:

建议我使用NSMetaDataQuery 监控我的 iCloud 沙盒 (iOS) - 并且一切正常。

我正在尝试在NSMetadataQueryDidUpdateNotification 中使用NSMetadataQueryUpdateChangedItemsKey,以便有效地更新文件系统的内部模型。我面临的挑战是,当文件被移动/重命名时,我如何知道原始文件路径 - 以便我可以更新我的模型?

看来NSMetaDataItem 对象是持久的(即当路径更改时更新相同的对象实例),因此我可以使用指针值作为我模型的一种索引。但是 - 我会利用一个明显的实现细节(可能会改变。)也许 NSMetaDataItems 在内存不足时被回收?

任何人都知道应该怎么做(或者如果NSMetaDataItem 对象在NSMetaDataQuery 的生命周期内持续存在 - 并保持“附加”到同一个文件系统项目。)

【问题讨论】:

    标签: ios icloud nsmetadataquery


    【解决方案1】:

    是的,NSMetadataQuery 不提供查询先前路径的方法。

    当一个项目被移动时,它在 NSMetadataQuery 结果中的索引保持不变。所以我们可以复制结果的路径,当更新开始时,我们只需要检查复制数组的确切位置的 NSMetadataItem。

        if let updatedObj = obj.userInfo?[NSMetadataQueryUpdateChangedItemsKey] as! [NSMetadataItem]? {
    
            for it in updatedObj {
    
                let url = it.valueForAttribute(NSMetadataItemURLKey) as! NSURL
                let value = it.valueForAttribute(NSMetadataUbiquitousItemIsUploadedKey) as! NSNumber
    
                print("Path: " + url.path!)
                print("Updated: " + value.stringValue)
    
                let index = metaDataQuery.indexOfResult(it)
                let prevPath = duplicatedPathArray[index]
    
                if (prevPath != url.path!) {
                    print("File Moved. Previous path: " + prevPath)
                    duplicatePath()
                }
            }
        }
    

    确保每次添加或删除文件时都更新数组。

    【讨论】:

    • 如果在同一批更新中删除并重新添加同一个文件,这会很棘手。但可能可以处理。
    【解决方案2】:

    文档提到结果适用于 Cocoa 绑定,这意味着这些对象很可能是持久的。

    我使用更硬核的NSFilePresenterNSMetadataQuery 组合并排运行来监视容器中的文档。 NSFilePresenter 有方便的 API 来检测文件何时被移动:

    func presentedSubitem(at oldURL: URL, didMoveTo newURL: URL)

    为此,当您在容器中移动文件时,您必须明确通知文件协调器您正在移动文件(请参阅第 1-3 点):

    let fc = NSFileCoordinator()
    var error: NSError?
    
    fc.coordinate(writingItemAt: from, options: .forMoving, writingItemAt: to, options: .forReplacing, error: &error, byAccessor: {
        (fromURL, toURL) in
        do {
            // 1
            fc.item(at: fromURL, willMoveTo: toURL)
    
            try FileManager.default.moveItem(at: fromURL, to: toURL)
    
            // 2
            fc.item(at: fromURL, didMoveTo: toURL)
        } catch {
            // 3
            fc.item(at: fromURL, didMoveTo: fromURL)
        }
    })
    

    【讨论】:

      猜你喜欢
      • 2011-12-18
      • 2013-12-16
      • 2019-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-20
      • 2018-04-21
      • 2014-02-09
      相关资源
      最近更新 更多