CloudKit,重新安装应用程序后,如何将我的订阅重置为当前记录状态?

Posted

技术标签:

【中文标题】CloudKit,重新安装应用程序后,如何将我的订阅重置为当前记录状态?【英文标题】:CloudKit, after reinstalling an app how do I reset my subscriptions to current status of records? 【发布时间】:2018-12-01 11:05:29 【问题描述】:

我正在处理这样一个场景,用户之前删除了应用程序,现在又重新安装了它。

它正在访问我的 delta fetch 功能,该功能正在接收许多旧订阅通知,主要是删除。但不下载当前记录。

我现在正在添加代码以对每种记录类型执行提取以下载所有数据。

我想重置 delta fetch 服务器令牌,因此该应用不必处理旧订阅通知。但是我找不到如何做到这一点,也许这是不可能的。

【问题讨论】:

【参考方案1】:

当您说“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 记录中(您必须将其添加为新字段)。每次 previousServerChangeTokenrecordZoneFetchCompletionBlock 中发生变化时,您都必须将其保存回 iCloud 中的用户记录。

【讨论】:

是的,但我需要一些方法来在重新安装应用程序时获取当前令牌,而不是第一个令牌。因为我将进行获取以获取所有数据。然后我想使用一个令牌来进行未来的更改。 如果用户在 ios 上删除应用程序,那么所有UserDefaults 也会被删除。据我所知,没有办法保留令牌。相反,您可以做的是在 CloudKit 上保留一个表,该表将 Users 唯一 ID(使用 fetchUserRecordID() 获取)与时间戳或令牌相匹配。当该用户访问应用程序时,获取时间戳或令牌并相应地同步。这是在应用删除/安装过程中为该用户保留数据的唯一方法。 好的,谢谢,但是有没有办法将所有通知都标记为已读? 您可以根据与用户 ID 关联的时间戳查询数据,因此您只能获取该日期之后的记录。这只是使用CKQuery 进行的初始获取,之后您可以使用previousChangeToken 来了解要获取的内容。 Erm,所以基本上只是根据 'fetchUserRecordID()' 提供的设备 ID 存储 'previousChangeToken' ?无论应用程序是否被删除,该设备 ID 每次都相同吗?谢谢。如果是这样,您可以更新您的答案,以便我接受它:)

以上是关于CloudKit,重新安装应用程序后,如何将我的订阅重置为当前记录状态?的主要内容,如果未能解决你的问题,请参考以下文章

我可以将 CloudKit 数据转移到新的 Container 中吗?

CoreData + CloudKit 仅在最小化和重新打开应用程序后同步

更新后应用程序崩溃但重新安装后没有

CloudKit 重新索引数据需要很长时间

CloudKit iOS:用户无法删除应用程序数据

切换视图控制器后如何保持加载来自 iCloud(CloudKit)的数据