将 CloudKit 记录保存到本地文件保存除 CKAsset 之外的所有字段
Posted
技术标签:
【中文标题】将 CloudKit 记录保存到本地文件保存除 CKAsset 之外的所有字段【英文标题】:Saving CloudKit Record to Local File Saves all fields Except CKAsset 【发布时间】:2019-01-25 04:41:00 【问题描述】:我正在尝试将 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 场景)当然不见了。
任何指导将不胜感激。
【问题讨论】:
cloudKit 有很多延迟,当您提交请求时关闭触发,而不是在数据实际可用时触发。尝试在阅读后添加十秒的延迟 [确保],然后再保存,看看它是否能解决您的问题。如果确实是问题所在,请尝试在使用数据的资产值设置局部变量后使用 getter/setter 来触发保存。 我认为这不是问题所在。我拆分功能进行测试 - 我下载 CKRecords,将它们放在一个数组中,然后将它们显示在 tableView(包括 SCNScene)中。所以我知道我有数据。然后我使用该已知良好数组的按钮启动保存到文档目录功能。 在我从事的几乎每个项目中,我都会遇到一些 ios 框架错误。第一次发生时,我花了好几天才弄明白,也许就是这么微妙。通过代码工作,尝试只保存资产文件,忘记字符串。尝试更改用于保存它的代码。 【参考方案1】:CKAsset 只是一个文件引用。 CKAsset 的 fileURL 属性是实际文件所在的位置。如果您保存一个 SKAsset,那么您只保存对该文件的引用。这样做时,您必须记住此 url 位于缓存位置,如果空间不足,可以清除该位置。
你可以做两件事。 1.读取备份CKAsset时,还要检查文件是否位于fileURL位置。如果该文件不存在,则从 CloudKit 再次读取它。 2. 还将文件从 fileURl 备份到您的文档文件夹。当您从备份中读取 CKAsset 时,不要从 fileURL 读取文件,而是从您将其放入文档过滤器的位置读取文件。
【讨论】:
以上是关于将 CloudKit 记录保存到本地文件保存除 CKAsset 之外的所有字段的主要内容,如果未能解决你的问题,请参考以下文章