1

我正在尝试将一组 CKRecords 保存到文档目录中,以便快速启动和离线访问。

从 CloudKit 下载 CKRecords 工作正常,我可以毫无问题地在每条记录中使用 CKAsset。但是,当我将下载的 CKRecords 数组保存到本地文件时,CKAsset 不包含在数据文件中。我可以从保存到文档目录的文件大小中看出这一点。如果我将磁盘文件重组为 CKRecords 数组,我可以检索除 CKAsset 之外的所有字段。除了系统字段和 CKAsset 字段之外,所有字段都是字符串。

用于测试 - 我有 10 个 CloudKit 记录,每个记录有六个小的字符串字段和一个大约 500KB 的 CKAsset。当我检查文档中生成的文件的大小时,文件大小约为 15KB。

这是保存数组的函数。AppDelegate.ckStyleRecords 是下载的 CKRecords 的静态数组。

func saveCKStyleRecordsToDisk() {

    if AppDelegate.ckStyleRecords.count != 0 {

        let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let docsDirectoryURL = urls[0]
        let ckStyleURL = docsDirectoryURL.appendingPathComponent("ckstylerecords.data")

        do {
            let data : Data = try NSKeyedArchiver.archivedData(withRootObject: AppDelegate.ckStyleRecords, requiringSecureCoding: true)

            try data.write(to: ckStyleURL, options: .atomic)
            print("data write ckStyleRecords successful")

        } catch {
            print("could not save ckStyleRecords to documents directory")
        }

    }//if count not 0

}//saveCKStyleRecordsToDisk

这是重构数组的函数。

func checkForExistenceOfCKStyleRecordsInDocuments(completion: @escaping ([CKRecord]) -> Void) {

    let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    let docsDirectoryURL = urls[0]
    let ckStyleURL = docsDirectoryURL.appendingPathComponent("ckstylerecords.data")

    var newRecords : [CKRecord] = []
    if FileManager.default.fileExists(atPath: ckStyleURL.path) {

        do {
            let data = try Data(contentsOf:ckStyleURL)

            //yes, I know this has been deprecated, but I can't seem to get the new format to work
            if let theRecords: [CKRecord] = try NSKeyedUnarchiver.unarchiveObject(with: data) as? [CKRecord] {
                        newRecords = theRecords
                        print("newRecords.count is \(newRecords.count)")
            }

        } catch {
            print("could not retrieve ckStyleRecords from documents directory")
        }

    }//if exists

    completion(newRecords)

}//checkForExistenceOfckStyleRecordsInDocuments

调用上面的:

    kAppDelegate.checkForExistenceOfCKStyleRecordsInDocuments { (records) in
        print("in button press and records.count is \(records.count)")

        //this is just for test
        for record in records {
            print(record.recordID.recordName)
        }

        AppDelegate.ckStyleRecords = records

    }//completion block

刷新使用 ckStyleRecords 数组的 tableView 后,所有数据似乎都是正确的,除了 CKAsset(在本例中是 SceneKit 场景)当然丢失了。

任何指导将不胜感激。

4

1 回答 1

0

CKAsset 只是一个文件引用。CKAsset 的 fileURL 属性是实际文件所在的位置。如果您保存 SKAsset,那么您只保存对文件的引用。这样做时,您必须记住此 url 位于缓存位置,如果空间不足,可以清除该位置。

你可以做两件事。1.读取备份CKAsset时,还要检查文件是否位于fileURL位置。如果该文件不存在,则从 CloudKit 再次读取它。2. 还将文件从 fileURl 备份到您的文档文件夹。当您从备份中读取 CKAsset 时,不要从 fileURL 读取文件,而是从您将其放入文档过滤器的位置读取文件。

于 2019-01-30T07:10:54.923 回答