Save CKServerChangeToken to Core Data

馋奶兔 提交于 2019-11-30 16:01:56

问题


I use CloudKit and Core Data with Swift to synchronize my data. Therefore I created Subscriptions and after getting a notification I fetch the new data from the cloud to update my Core Data. This is the recommended way to handle this update. For fetching data changes I can insert a CKServerChangeToken to fetch just the new stuff. My question is how to save the token to Core Data for later fetch requests? For CKRecords there is a method to save only the metadata but there isn't anything like this for CKServerChangeToken. Does anyone have an idea?

Best regards, Jannik


回答1:


The CKServerChangeToken is an opaque data object that inherits from NSObject and conforms to the NSCopying protocol, which means that you can use a NSKeyedArchiver and NSKeyedUnarchiver to convert the token to an (NS)Data object.

A (NS)Data object can then be stored into a property on any NSManagedObject. Alternatively you could store this data in the (NS)UserDefaults. Here's one way to accomplish this as a swift extension to 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")
            }
        }
    }
}

With this extension you can get/set the CKServerChangeToken right from (NS)UserDefaults with:

let changeToken = UserDefaults.standard.serverChangeToken
UserDefaults.standard.serverChangeToken = `newToken`

As pointed out, the NSKeyedUn/Archiver calls were deprecated in iOS 12. Here is an updated example.

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")
            }
        }
    }
}


来源:https://stackoverflow.com/questions/40589140/save-ckserverchangetoken-to-core-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!