2015-08-24 2 views
3

Я наблюдаю за своей изолированной песочницей iCloud (iOS) с использованием NSMetaDataQuery - и все работает хорошо.iCloud NSMetadataQuery и обновления (NSMetadataQueryUpdateChangedItemsKey)

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

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

Каждый знает, как это должно быть сделано (или, если это на самом деле так, что NSMetaDataItem объекты сохраняются в течение всего срока службы 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() 
      } 
     } 
    } 

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

+0

Это сложно, если один и тот же файл удаляется и повторно добавляется в пределах той же серии обновлений. Но, вероятно, можно справиться. – Andy

0

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

Я использую более хардкорную комбинацию 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) 
    } 
})