【问题标题】:CloudKit on iOS won't fetch all of my desired recordsiOS 上的 CloudKit 不会获取我想要的所有记录
【发布时间】:2018-08-26 20:15:29
【问题描述】:

我用于使用 CloudKit 为我的应用获取记录的 api 不再正常工作。它只是在一两个星期前才开始这样做。它从公共数据库中获取很好,而不是从私有数据库中获取。

例如,我有一个名为“Part”的记录类型,其中包含一些值,包括“dateamp”字段。第一次启动应用程序时,它应该使用 CKQueryOperation 在私有数据库中获取 Part(和其他)的所有记录,然后在后续启动时,它使用 CKFetchRecordZoneChangesOperation 获取任何新记录。在我的个人 iCloud 帐户中,我有超过 1,000 条这样的记录。但是查询操作和获取更改操作只能获取完全相同的 107 条记录,不能再获取更多。这不是 resultLimits 的问题,我已经实现了对 CKQueryCursor 的检查。作为一个实验,我给它一个谓词,只获取时间戳为 2018 年 1 月或更晚的记录——它返回 0 记录。还有另一种记录类型,在我的数据库中有 12 条记录,但只有 1 正在同步。

我将同步类设计为跨平台 API。它适用于我的 iOS、macOS 和 tvOS 目标。 macOS 目标同步良好,即使它使用完全相同的代码行。 iOS 和 tvOS 已经运行了将近 2 年。除了现在在 NSOperation 子类中使用该类之外,几乎没有任何改变。我在多个 iPhone、iPad、iOS 模拟器实例、iOS 版本、Xcode 版本上进行了尝试。我尝试了不同的 iCloud 帐户。我不知道问题是什么。但是这个错误使我无法发布急需的更新。我想这可能只是 Apple 在开发环境中的一个错误,并且在公开发布时可以正常工作,但我害怕禁用我的所有用户。

 protocol CloudData {
    var privateDatabase : CKDatabase { get }
 }

 extension CloudData {
    var privateDatabase : CKDatabase {
       return CKContainer (identifier: "iCloud...").privateDatabase
    }
 }

 final class CloudSync : CloudData {

    func initialSync {

         ...

         // Create an operation to fetch all PARTS
        let partQuery = CKQuery (recordType: "Part", predicate: NSPredicate(value: true))
        let partOperation = CKQueryOperation (query: partQuery)
        partOperation.recordFetchedBlock = { partRecords += [$0] }
        partOperation.zoneID = zoneID
        partOperation.queryCompletionBlock = { cursor, error in

            if let cursorObj = cursor {

                print("Initial Sync - Cursor Found Parts")

                let newOp = CKQueryOperation (cursor: cursorObj)
                newOp.recordFetchedBlock = partOperation.recordFetchedBlock
                newOp.queryCompletionBlock = partOperation.queryCompletionBlock
                self.privateDatabase.add(newOp)

                return
            }
            self.progress.completedUnitCount += 1
            print ("Initial Sync - Part Objects Fetched")


        }

        partOperation.database = privateDatabase

        ...
    }

 }

【问题讨论】:

  • (1) 显示定义 privateDatabase 的行。 (2) 以下是什么意思? “例如,我有一条名为“Part”的记录,其中包含一些值,包括“dateamp”字段。第一次启动应用程序时,它应该在私有数据库中获取 Part(和其他)的所有记录使用 CKQueryOperation,然后在后续启动时,它会使用 CKFetchRecordZoneChangesOperation 获取任何新的。”部分是记录?并试图获取 Part(记录)的所有记录?这没有意义。
  • 我对 2 号表示歉意。我错过了输入我的描述。 “部分”是一个记录类型。在 Core Data 术语中,它将是一个“实体”。因此,例如,用户将使用 { datestamp = Mar 2018, name = Dan's Part, description = part for Dan} 之类的数据创建一个“Part”CKRecord。所以应用程序第一次启动时,它会获取该类型的所有记录。然后,它只获取添加的新记录 - 就像他们有第二个添加记录的设备一样,那么第一个设备将使用 CKFetchRecordZoneChanges 获取第二个设备创建的新记录。
  • “privateDatabase”只是一个在协议中定义并在协议扩展中实现的属性。像这样 - var privateDatabase : CKDatabase { return CKContainer (identifier: "iCloud....").privateDatabase } 。 CloudSync 类符合协议。为简洁起见,我只是省略了上面示例中类定义中的所有协议一致性。
  • 如果您建议不能仅为私有数据库获取数据,那么您可能需要处理安全角色。
  • 我想过。我将对此进行更多研究。但事实是我可以从私有数据库中获取,只是它只能获取有限数量的我的记录。它从不出错,只返回我正在查询的记录的一小部分——我知道这些记录在那里。每一条记录都是我创造的。除此之外,相同的数据库,使用相同的 API,查询相同的记录,使用相同的 iCloud 帐户,每次都适用于我的应用程序的 macOS 版本。如果获取所有 1,200 条记录。我可能不得不将我的一个 TSI 用于 Apple。

标签: ios swift cloudkit


【解决方案1】:

这很可能是 CloudKit 错误,提交错误报告可能是最佳选择。 CloudKit 还不完善。

【讨论】:

    【解决方案2】:

    如果我没有在游标块中将查询操作分配给主操作,我通常会遇到大提取(超过 2 个游标)的问题。

    尝试在self.privateDatabase.add(newOp) 的正上方添加partOperation = newOp

    我认为您不需要光标块末尾的return。我的电话都没有。

    看看有没有帮助。

    【讨论】:

    • 我知道,我在上面代码中的递归方式通常会出现问题(对于光标操作)。我对上面的代码进行了缩写以使其更易于阅读。在完整类中,查询/游标操作被初始化并从函数返回;这避免了只能像您描述的那样运行两次查询的问题。我知道退货是不必要的;当我有很多代码时,这只是我为自己的利益而做的事情;让自己清楚地知道执行将在那里结束。
    • 感谢您的建议,不过我找到了问题的根源。请参阅下面我自己的答案。
    【解决方案3】:

    我发现了这个问题,它不是 CloudKit 错误。这实际上对我来说有点愚蠢。在我的 iCloud 权利文件中,我有一行明确地将 iCloud 会话设置为“生产”环境,而不是“开发”环境。我不知道为什么我在那里有那个;我一定是在生产公共商店中调试了一些东西,只是在我完成后忘记撤消它。

    尽管如此,我认为它应该仍然可以正常工作。它可能没有获取我所有的私人记录,因为它们中的大多数都在开发环境中,但是当我进行调试时,我也保存了一些到生产环境中。另外,我不明白为什么iOS模拟器在通过生产环境时无法从任何一个数据库中获取记录。

    但只要它现在可以工作,我就可以。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-08
      • 2015-11-04
      • 1970-01-01
      • 2012-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多