我使用CloudKit和Core Data与Swift同步我的数据。因此,我创建了订阅,在收到通知后,我从云端获取新数据以更新我的核心数据。这是处理此更新的推荐方法。为了获取数据更改,我可以插入一个CKServerChangeToken来获取新的东西。我的问题是如何将令牌保存到Core Data以便以后获取请求?对于CKRecords,有一种只保存元数据的方法,但CKServerChangeToken没有这样的方法。有没有人有想法?
最好的问候,Jannik
答案 0 :(得分:18)
CKServerChangeToken是一个不透明的数据对象,它继承自NSObject并符合NSCopying协议,这意味着您可以使用NSKeyedArchiver和NSKeyedUnarchiver将令牌转换为(NS)Data对象。
然后可以将(NS)数据对象存储到任何NSManagedObject上的属性中。或者,您可以将此数据存储在(NS)UserDefaults中。作为UserDefaults的快速扩展,这是实现此目的的一种方法:
import Foundation
import CloudKit
public extension UserDefaults {
public var serverChangeToken: CKServerChangeToken? {
get {
guard let data = self.value(forKey: "ChangeToken") as? Data else {
return nil
}
guard let token = NSKeyedUnarchiver.unarchiveObject(with: data) as? CKServerChangeToken else {
return nil
}
return token
}
set {
if let token = newValue {
let data = NSKeyedArchiver.archivedData(withRootObject: token)
self.set(data, forKey: "ChangeToken")
} else {
self.removeObject(forKey: "ChangeToken")
}
}
}
}
使用此扩展程序,您可以从(NS)UserDefaults获取/设置CKServerChangeToken:
let changeToken = UserDefaults.standard.serverChangeToken
UserDefaults.standard.serverChangeToken = `newToken`
正如所指出的,在iOS 12中不推荐使用NSKeyedUn / Archiver调用。这是一个更新的示例。
import Foundation
import CloudKit
public extension UserDefaults {
public var serverChangeToken: CKServerChangeToken? {
get {
guard let data = self.value(forKey: "ChangeToken") as? Data else {
return nil
}
let token: CKServerChangeToken?
do {
token = try NSKeyedUnarchiver.unarchivedObject(ofClass: CKServerChangeToken.self, from: data)
} catch {
token = nil
}
return token
}
set {
if let token = newValue {
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: token, requiringSecureCoding: false)
self.set(data, forKey: "ChangeToken")
} catch {
// handle error
}
} else {
self.removeObject(forKey: "ChangeToken")
}
}
}
}