Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/103.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 将CKServerChangeToken保存到核心数据_Ios_Swift_Core Data_Synchronization_Cloudkit - Fatal编程技术网

Ios 将CKServerChangeToken保存到核心数据

Ios 将CKServerChangeToken保存到核心数据,ios,swift,core-data,synchronization,cloudkit,Ios,Swift,Core Data,Synchronization,Cloudkit,我使用CloudKit和核心数据与Swift同步我的数据。因此,我创建了订阅,在收到通知后,我从云中获取新数据以更新我的核心数据。这是处理此更新的推荐方法。为了获取数据更改,我可以插入一个CKServerChangeToken来获取新的内容。我的问题是如何将令牌保存到核心数据中,以供以后的获取请求使用?对于CKRecords,有一种只保存元数据的方法,但对于CKServerChangeToken,没有类似的方法。有人有主意吗 值得一提的是,JannikCKServerChangeToken是一个

我使用CloudKit和核心数据与Swift同步我的数据。因此,我创建了订阅,在收到通知后,我从云中获取新数据以更新我的核心数据。这是处理此更新的推荐方法。为了获取数据更改,我可以插入一个CKServerChangeToken来获取新的内容。我的问题是如何将令牌保存到核心数据中,以供以后的获取请求使用?对于CKRecords,有一种只保存元数据的方法,但对于CKServerChangeToken,没有类似的方法。有人有主意吗


值得一提的是,Jannik

CKServerChangeToken是一个不透明的数据对象,它继承自NSObject并符合NSCopying协议,这意味着您可以使用NSKeyedArchiver和NSKeyedUnachiver将令牌转换为(NS)数据对象

然后,可以将(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")
            }
        }
    }
}

谢谢@richardpiazza。有人能确认你确实应该缓存更改令牌的时间比应用程序运行的时间长吗?也就是说,不只是在内存中?文档对我来说似乎模棱两可。@vegashacker您不想在调用中提供更改标记的唯一原因是强制检索记录区域中的所有更改。请看2016年WWDC的CloudKit最佳实践视频。以下是相关时间索引的链接:WWDC 2016视频“CloudKit最佳实践,15英尺45英寸”说,它需要精确地跨运行进行缓存,以便您可以知道应用程序的数据缓存是否最新。请参阅自iOS12起,这将收到警告,因为“NSKeyedUnarchiver.unarchiveObject(with:data)as?CKServerChangeToken”已被弃用。感谢iOS12更新!文档因NSKeyedArchiver更改而被破坏