CloudKit游标返回的结果超出预期

时间:2018-02-21 07:03:03

标签: ios swift cloudkit

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

我保存了在每个creationDate上创建的记录数。我获得的每个日期的数字远远高于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)
}

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

P.S。对于它的价值,当我使用调试器时,将结果限制设置为5无效。不确定这是否是相关问题。

1 个答案:

答案 0 :(得分:0)

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

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