文件存在于 iCloud 中,但 query.resultCount = 0

File exists in iCloud, but query.resultCount = 0

应用使用iCloud存储符合Codable协议的对象

在重新安装应用程序或在新设备上安装应用程序的情况下,我尝试使用 NSMetadataQuery 从 iCloud 的现有文件中获取数据 - 但 query.resultCount = 0。

我认为我的问题是关于以正确的方式设置 NSMetadataQuery 谓词。

问题请多多指教

class ViewController: UIViewController {

@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var weightLabel: UILabel!

@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var weightTextField: UITextField!

let fileManager = FileManager.default

var iCloudContainer: URL? {
    return FileManager().url(forUbiquityContainerIdentifier: nil)
}

func getFilePath(container: URL, fileName: String) -> String {
    let filePath = container.appendingPathComponent(fileName).path

    return filePath
}

lazy var metadataQuery : NSMetadataQuery = {
    let query = NSMetadataQuery()

    query.searchScopes = [NSMetadataQueryUbiquitousDocumentsScope]
    var pred = NSPredicate(format: "NOT %K.pathExtension = '.'", NSMetadataItemFSNameKey)
    query.predicate = pred

    return query
}()

override func viewDidLoad() {
    super.viewDidLoad()

    self.metadataQuery.start()

    NotificationCenter.default.addObserver(self, selector: #selector(refreshFileList), name: NSNotification.Name.NSMetadataQueryDidUpdate, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(refreshFileList), name: NSNotification.Name.NSMetadataQueryDidFinishGathering, object: nil)
}

deinit {
    NotificationCenter.default.removeObserver(self)
}

@objc func refreshFileList() {
    print(metadataQuery.resultCount)
    metadataQuery.enumerateResults { (item: Any, index: Int, stop: UnsafeMutablePointer<ObjCBool>) in
        let metadataItem = item as! NSMetadataItem

        if isMetadataItemDownloaded(item: metadataItem) == false {

            let url = metadataItem.value(forAttribute: NSMetadataItemURLKey) as! URL

            try? FileManager.default.startDownloadingUbiquitousItem(at: url)
        }
    }

    let container = self.iCloudContainer
    let filePath = getFilePath(container: container!, fileName: "Person")

    if let jsonData = NSKeyedUnarchiver.unarchiveObject(withFile: filePath) as? Data {
        if let person = try? JSONDecoder().decode(Person.self, from: jsonData) {
            nameLabel.text = person.name
            weightLabel.text = String(person.weight)
        } else {
            nameLabel.text = "NOT decoded"
            weightLabel.text = "NOT decoded"
        }
    } else {
        nameLabel.text = "NOT unarchived"
        weightLabel.text = "NOT unarchived"
    }
}

func isMetadataItemDownloaded(item : NSMetadataItem) -> Bool {
    if item.value(forAttribute: NSMetadataUbiquitousItemDownloadingStatusKey) as? String == NSMetadataUbiquitousItemDownloadingStatusCurrent {
        return true
    } else {
        return false
    }
}

@IBAction func saveButtonPressed(_ sender: UIButton) {
    let container = self.iCloudContainer
    let filePathe = getFilePath(container: container!, fileName: "Person")

    let person = Person(name: nameTextField.text!, weight: Double(weightTextField.text!)!)
    let jsonData = try? JSONEncoder().encode(person)
    NSKeyedArchiver.archiveRootObject(jsonData!, toFile: filePathe)
}

}

首先谓词的格式应该是

 query.predicate = NSPredicate(format: "%K == %@", NSMetadataItemFSNameKey, "Person")

其次,你在容器中显示保存文件是这样的

let filePath = container.appendingPathComponent("Documents").appendingPathComponent(fileName).path

文件路径必须是/Documents/File

没有Documents目录,查询找不到文件