CloudKit,重新安装应用程序后,如何将我的订阅重置为当前记录状态?
CloudKit, after reinstalling an app how do I reset my subscriptions to current status of records?
我正在处理这样一种情况,用户之前删除了该应用程序,现在又重新安装了它。
它影响了我的增量获取功能,该功能正在接收大量旧的订阅通知,主要是删除通知。但不下载当前记录。
我现在正在添加代码以对每种记录类型执行提取以下载所有数据。
我想重置增量提取服务器令牌,这样应用程序就不必处理旧的订阅通知。但是我找不到如何做到这一点,也许这是不可能的。
当你说 "delta fetch server token" 时,你指的是 CKServerChangeToken
(documentation) 吗?您是否尝试在 CloudKit private 数据库中同步?
假设这是真的,下面是我如何从私有数据库获取更改并跟踪同步令牌的示例:
//MARK: Fetch Latest from CloudKit from private DB
func fetchPrivateCloudKitChanges(){
print("Fetching private changes...")
//:::
let privateZoneId = CKRecordZone.ID(zoneName: CloudKit.zoneName, ownerName: CKCurrentUserDefaultName)
/----
let options = CKFetchRecordZoneChangesOperation.ZoneOptions()
options.previousServerChangeToken = previousChangeToken
let operation = CKFetchRecordZoneChangesOperation(recordZoneIDs: [privateZoneId], optionsByRecordZoneID: [recordZoneID:options])
//Queue up the updated records to process below
var records = [CKRecord]()
operation.recordChangedBlock = { record in
records.append(record)
}
operation.recordWithIDWasDeletedBlock = { recordId, type in
//Process a deleted record in your local database...
}
operation.recordZoneChangeTokensUpdatedBlock = { (zoneId, token, data) in
// Save new zone change token to disk
previousChangeToken = token
}
operation.recordZoneFetchCompletionBlock = { zoneId, token, _, _, error in
if let error = error {
print(error)
}
// Write this new zone change token to disk
previousChangeToken = token
}
operation.fetchRecordZoneChangesCompletionBlock = { error in
if let error = error {
print(error
}else{
//Success! Process all downloaded records from `records` array above...
//records...
}
}
CloudKit.privateDB.add(operation)
}
//Change token property that gets saved and retrieved from UserDefaults
var previousChangeToken: CKServerChangeToken? {
get {
guard let tokenData = defaults.object(forKey: "previousChangeToken") as? Data else { return nil }
return NSKeyedUnarchiver.unarchiveObject(with: tokenData) as? CKServerChangeToken
}
set {
guard let newValue = newValue else {
defaults.removeObject(forKey: "previousChangeToken")
return
}
let data = NSKeyedArchiver.archivedData(withRootObject: newValue)
defaults.set(data, forKey: "previousChangeToken")
}
}
您的具体情况可能略有不同,但我认为在与 CloudKit.
保持同步时通常应该这样工作
更新
您可以尝试将 previousServerChangeToken
存储在 CloudKit 中的 Users
记录中(您必须将其添加为新字段)。每次 previousServerChangeToken
在 recordZoneFetchCompletionBlock
中发生变化时,您都必须将其保存回 iCloud 中的用户记录。
我正在处理这样一种情况,用户之前删除了该应用程序,现在又重新安装了它。
它影响了我的增量获取功能,该功能正在接收大量旧的订阅通知,主要是删除通知。但不下载当前记录。
我现在正在添加代码以对每种记录类型执行提取以下载所有数据。
我想重置增量提取服务器令牌,这样应用程序就不必处理旧的订阅通知。但是我找不到如何做到这一点,也许这是不可能的。
当你说 "delta fetch server token" 时,你指的是 CKServerChangeToken
(documentation) 吗?您是否尝试在 CloudKit private 数据库中同步?
假设这是真的,下面是我如何从私有数据库获取更改并跟踪同步令牌的示例:
//MARK: Fetch Latest from CloudKit from private DB
func fetchPrivateCloudKitChanges(){
print("Fetching private changes...")
//:::
let privateZoneId = CKRecordZone.ID(zoneName: CloudKit.zoneName, ownerName: CKCurrentUserDefaultName)
/----
let options = CKFetchRecordZoneChangesOperation.ZoneOptions()
options.previousServerChangeToken = previousChangeToken
let operation = CKFetchRecordZoneChangesOperation(recordZoneIDs: [privateZoneId], optionsByRecordZoneID: [recordZoneID:options])
//Queue up the updated records to process below
var records = [CKRecord]()
operation.recordChangedBlock = { record in
records.append(record)
}
operation.recordWithIDWasDeletedBlock = { recordId, type in
//Process a deleted record in your local database...
}
operation.recordZoneChangeTokensUpdatedBlock = { (zoneId, token, data) in
// Save new zone change token to disk
previousChangeToken = token
}
operation.recordZoneFetchCompletionBlock = { zoneId, token, _, _, error in
if let error = error {
print(error)
}
// Write this new zone change token to disk
previousChangeToken = token
}
operation.fetchRecordZoneChangesCompletionBlock = { error in
if let error = error {
print(error
}else{
//Success! Process all downloaded records from `records` array above...
//records...
}
}
CloudKit.privateDB.add(operation)
}
//Change token property that gets saved and retrieved from UserDefaults
var previousChangeToken: CKServerChangeToken? {
get {
guard let tokenData = defaults.object(forKey: "previousChangeToken") as? Data else { return nil }
return NSKeyedUnarchiver.unarchiveObject(with: tokenData) as? CKServerChangeToken
}
set {
guard let newValue = newValue else {
defaults.removeObject(forKey: "previousChangeToken")
return
}
let data = NSKeyedArchiver.archivedData(withRootObject: newValue)
defaults.set(data, forKey: "previousChangeToken")
}
}
您的具体情况可能略有不同,但我认为在与 CloudKit.
保持同步时通常应该这样工作更新
您可以尝试将 previousServerChangeToken
存储在 CloudKit 中的 Users
记录中(您必须将其添加为新字段)。每次 previousServerChangeToken
在 recordZoneFetchCompletionBlock
中发生变化时,您都必须将其保存回 iCloud 中的用户记录。