iCloud NSMetadataQuery и обновления (NSMetadataQueryUpdateChangedItemsKey)

Я отслеживаю свою песочницу iCloud (iOS) с помощью NSMetaDataQuery (рекомендуется), и все работает хорошо.

Я пытаюсь использовать NSMetadataQueryUpdateChangedItemsKey в NSMetadataQueryDidUpdateNotification для эффективного обновления моей внутренней модели файловой системы. Проблема, с которой я сталкиваюсь, заключается в том, что когда файл перемещается/переименовывается, как я могу узнать исходный путь к файлу, чтобы я мог обновить свою модель?

Похоже, что объекты NSMetaDataItem являются постоянными (т. е. один и тот же экземпляр объекта обновляется при изменении пути), поэтому я мог бы использовать значение указателя в качестве своего рода индекса в моей модели. Однако - я бы воспользовался очевидной деталью реализации (которая может измениться). Возможно, NSMetaDataItems перерабатываются, когда заканчивается память?

Кто-нибудь знает, как это должно быть сделано (или действительно ли объекты NSMetaDataItem сохраняются в течение всего срока службы NSMetaDataQuery и остаются "привязанными" к одному и тому же элементу файловой системы.)


person Scotty    schedule 24.08.2015    source источник


Ответы (2)


Да, 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()
            }
        }
    }

Убедитесь, что вы обновляете массив каждый раз, когда файл добавляется или удаляется.

person strongwillow    schedule 01.09.2016
comment
Однако это сложно, если один и тот же файл удаляется и снова добавляется в одном и том же пакете обновлений. Но, вероятно, можно справиться. - person Ben Affleck; 28.11.2016

В документации упоминается, что результаты подходят для Cocoa Bindings, что означает, что, скорее всего, эти объекты являются постоянными.

Я использую более жесткую комбинацию NSFilePresenter и NSMetadataQuery, работающих параллельно, для мониторинга документов в контейнере. 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)
    }
})
person Ben Affleck    schedule 27.11.2016