简体   繁体   English

将 CloudKit 记录保存到本地文件 保存除 CKAsset 之外的所有字段

[英]Saving CloudKit Record to Local File Saves all fields Except CKAsset

I am trying to save an array of CKRecords to the documents directory in order to have fast startup and offline access.我正在尝试将一组 CKRecords 保存到文档目录中,以便快速启动和离线访问。

Downloading the CKRecords from CloudKit works fine and I am able to use the CKAsset in each record without issue.从 CloudKit 下载 CKRecords 工作正常,我能够在每条记录中使用 CKAsset 没有问题。 However, when I save the array of CKRecords that I downloaded to a local file, the CKAsset is not included in the data file.但是,当我将下载的 CKRecords 数组保存到本地文件时,数据文件中不包含 CKAsset。 I can tell this from the size of the file saved to the documents directory.我可以从保存到文档目录的文件大小中看出这一点。 If I reconstitute the disk file into an array of CKRecords, I can retrieve all of the fields except the CKAsset.如果我将磁盘文件重组为 CKRecords 数组,则可以检索除 CKAsset 之外的所有字段。 Other than the system fields, and the CKAsset field, all of the fields are Strings.除了系统字段和CKAsset 字段之外,所有字段都是字符串。

For testing - I have 10 CloudKit records each with six small String fields and a CKAsset which is about 500KB.为了测试 - 我有 10 个 CloudKit 记录,每个记录有六个小字符串字段和一个大约 500KB 的 CKAsset。 When I check the size of the resulting file in documents the file size is about 15KB.当我检查文档中生成的文件的大小时,文件大小约为 15KB。

Here's the function to save the array.这是保存数组的函数。 AppDelegate.ckStyleRecords is a static array of the downloaded CKRecords. 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

Here is the function to reconstitute the array.这是重构数组的函数。

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

Calling the above:调用上面的:

    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

Upon refreshing the tableView that uses the ckStyleRecords array, all data seems correct except the CKAsset (which in this case is a SceneKit scene) is of course missing.刷新使用 ckStyleRecords 数组的 tableView 后,除了 CKAsset(在本例中为 SceneKit 场景)当然丢失之外,所有数据似乎都是正确的。

Any guidance would be appreciated.任何指导将不胜感激。

A CKAsset was just a file reference. CKAsset 只是一个文件引用。 the fileURL property of the CKAsset is where the actual file is located. CKAsset 的 fileURL 属性是实际文件所在的位置。 If you save a SKAsset then you only save the reference to the file.如果您保存 SKAsset,则您只保存对文件的引用。 When doing that you do have to remember that this url is on a cache location which could be cleared if you are low on space.执行此操作时,您必须记住此 url 位于缓存位置,如果空间不足,可以将其清除。

You could do 2 things.你可以做两件事。 1. when reading your backup CKAsset, then also check if the file is located at the fileURL location. 1.在读取备份CKAsset时,还要检查文件是否位于fileURL位置。 If the file is not there, then read it again from CloudKit.如果文件不存在,则从 CloudKit 再次读取它。 2. Also backup the file from the fileURl to your documents folder. 2. 同时将文件从 fileURl 备份到您的文档文件夹。 When you read your CKAsset from your backup, then just don't read the file from fileURL but the location where you have put it in your documents filter.当您从备份中读取 CKAsset 时,不要从 fileURL 读取文件,而是从您将其放入文档过滤器的位置读取文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM