【问题标题】:CloudKit cursors returning more results than expectedCloudKit 游标返回比预期更多的结果
【发布时间】:2018-07-31 16:19:24
【问题描述】:

我正在尝试查询我的 CloudKit 数据库中指定 RecordType 的所有记录。因为我可能有超过 100 条该类型的记录,所以我使用 CloudKit 游标,它会分批返回记录,直到没有更多记录要返回(此时游标为零)。

我保存在每个创建日期创建的记录数。我得到的每个日期的数字都比 CloudKit 仪表板中这些日期的记录高得多。例如,有一天我在 CloudKit 仪表板上手动数了 110 条记录,我的代码显示有 256 条。另一天我数 2 时,我的代码显示有 7 条。

我考虑过的问题

  • 时区差异 - 不太可能,因为即使在前后几天都没有创建记录的日子里也会出现这些高计数。
  • 也许我多次计算相同的记录 - 我打印出 CloudKit 在所有游标查询中找到的所有 472 条记录的列表。从一些测试来看,该列表中似乎没有任何记录 ID 重复,并且所有记录都是正确的类型。 (这看起来很奇怪,我想知道我是否需要更多地查看该列表。)
  • 也许我对光标的使用存在误解。因此,这篇 StackOverflow 帖子。

这是我如何使用光标的代码。如果有人看到了什么,请告诉我!

// This is the main code that kicks off the cursor handling

let predicate = NSPredicate(value: true)
let query = CKQuery(recordType: recordType, predicate: predicate)
let sort = NSSortDescriptor(key: "creationDate", ascending: true) // so the 0th result is the earliest
query.sortDescriptors = [sort]
let operation1 = CKQueryOperation(query: query)
operation1.resultsLimit = 5
operation1.queryCompletionBlock = { (cursor, error) in
if error != nil {
    self.recordTypeErrorHandling(error: error as! CKError, uid: uid, appID: appID, recordType: recordType)
}
else {
    self.queryRecordsWithCursor(cursor: cursor, isFirstCheck: true, uid: uid, appID: appID, recordType: recordType)
}

CKContainer.default().publicCloudDatabase.add(operation1)

// Related functions

// adapted from: https://gist.github.com/evermeer/5df7ad1f8db529893f40
func queryRecordsWithCursor(cursor: CKQueryCursor?, isFirstCheck: Bool, uid: String, appID: String, recordType: String) {

    guard let theCursor = cursor else { return }
    let operation = CKQueryOperation(cursor: theCursor)

    // happens each time a record is received
    operation.recordFetchedBlock = { [recordType] record in
        if self.recordTypeToRecordListDict[recordType] == nil {
            self.recordTypeToRecordListDict[recordType] = [record]
        }
        else {
            self.recordTypeToRecordListDict[recordType]?.append(record)
        }
    }
    // happens when all records are done for that cursor
    operation.queryCompletionBlock = { [recordType] cursor, error in
        if error == nil {
            if cursor == nil { // cursor is nil => we've gotten all records, so save them
                self.saveRecordCounts(records: self.recordTypeToRecordListDict[recordType]!, uid: uid, appID: appID, recordType: recordType, isFirstCheck: isFirstCheck) // use isFirstCheck, not the value in the dictionary
            }
            else if self.recordTypeToRecordListDict[recordType] != nil {
                self.queryRecordsWithCursor(cursor: cursor, isFirstCheck: isFirstCheck, uid: uid, appID: appID, recordType: recordType) // recursive call. if we've gotten here, there's definitely a non-nil cursor
            }
        }
        else {
            self.recordTypeErrorHandling(error: error as! CKError, uid: uid, appID: appID, recordType: recordType)
        }
    }
    CKContainer.default().publicCloudDatabase.add(operation)
}

如果您需要更多我的代码,请告诉我!谢谢!

附:对于它的价值,当我逐步使用调试器时,将结果限制设置为 5 没有任何效果。不确定这是否是相关问题。

【问题讨论】:

  • 您认为要添加它们的数组已经有结果。您可能需要先清空它
  • 我确实在我的代码的另一部分清空了列表。无论如何,该列表没有重复,这表明不存在列表清除问题。

标签: ios swift cloudkit


【解决方案1】:

想通了。这是一个问题的组合。一个是我没有第一组记录的recordFetchedBlock。另一个问题是我有一个需要 DispatchGroup 来同步事物的 for 循环。

我学到的另一件重要事情 - 如果您在仪表板中查询 CloudKit 记录,则不一定会显示所有记录。

【讨论】:

    猜你喜欢
    • 2021-08-01
    • 2016-11-13
    • 1970-01-01
    • 2012-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多