我想从公共数据库中删除大约500个“访问”记录。CloudKit一次只给你100个记录,所以我就像下面这样利用CKQueryCursor来获取我想要的所有记录。
func fetchVisits(_ cursor: CKQueryCursor? = nil) {
print("fetchVisits \(cursor)")
var operation: CKQueryOperation!
if let cursor = cursor {
operation = CKQueryOperation(cursor: cursor)
} else {
let query = CKQuery(recordType: "Visit", predicate: NSPredicate(format: "Client IN %@ AND ANY Students IN %@", visitClients, visitStudents))
operation = CKQueryOperation(query: query)
}
operation.recordFetchedBlock = {
(record) in
totalVisits.append(record)
}
operation.queryCompletionBlock = {
(cursor, error) in
if let error = error {
//handle error
} else if let cursor = cursor {
self.fetchVisits(cursor)
} else {
//all done!
}
}
CKContainer.default().publicCloudDatabase.add(operation)
}我把这个函数称为:
fetchVisits()很好,它能让我得到所有需要的访问。控制台日志
fetchVisits nil
fetchVisits Optional(<CKQueryCursor: 0x174228140; id=4bb7887c326fc719, zone=(null)>)
fetchVisits Optional(<CKQueryCursor: 0x17422a320; id=f67fb25669486da9, zone=(null)>)
fetchVisits Optional(<CKQueryCursor: 0x174228380; id=7e87eb8b7cfe1a74, zone=(null)>)
fetchVisits Optional(<CKQueryCursor: 0x17422cc80; id=e77e47ef2b29c8a4, zone=(null)>)但现在的问题是,当我按下一个按钮时,我想刷新一下,现在它给了我这个错误:
“服务不可用”(6/2022);“http状态代码503请求失败”;30.0秒后重试
这是相当不言自明的,我想我是压倒了服务器,要求一个微不足道的500记录?所以我等待30秒,再次调用这个函数,现在我得到了这个错误。
“超出限制”(27/2023);服务器消息=“查询筛选器超过值的限制: 250用于容器
由于某些原因,我不能再次运行该函数。如果我重新启动应用程序,它可以再次正常工作,但只是第一次。此问题似乎特定于任何返回CKQueryCursor的表。我有其他的表,我点击的少于100条记录(所以光标是零),我可以多次拉那些没有任何问题。
发布于 2017-07-29 17:21:29
好的,我以前见过这种情况,问题是,我相信,CloudKit服务器上有一个bug。根据我的经验,这与复杂的查询有关。
如果尝试将谓词更改为:
NSPredicate(value: true)甚至可以通过删除任何部分来简化现有的部分,这可能足以修复它。
发布于 2017-07-27 10:34:16
在查询操作完成之前,您将请求更多的CKRecords到iCloud。
...
operation.queryCompletionBlock = {
(cursor, error) in
if let error = error {
//handle error
} else if let cursor = cursor {
self.fetchVisits(cursor)
} else {
//all done!
}
}
...函数self.fetchVisits(cursor)调用是在完成块中完成的,这意味着在当前操作完成之前,您正在请求更多的记录。
可能的解决方案是使用闭包(completionHandler),其中包含CKQueryCursor,当用户需要更多的记录(滚动一个表或其他什么)时,您再次调用self.fetchVisits,传递在闭包上收到的cursos。
发布于 2019-07-06 13:01:45
编辑:我想现在我找到了原因:
虽然我先前的回答(以下)是正确的,但它不适用于这个问题。
现在,我遇到了问题中提到的两个服务器错误,并对情况进行了调查。
我的设置如下:
我希望根据谓词中指定的条件下载iCloud记录的子集:
let doNotDownloadIfOlderFormat = "NOT " + iCloudRecordKeyName + " IN %@"
let doNotDownloadIfOlderPredicate = NSPredicate.init(format: doNotDownloadIfOlderFormat, doNotDownloadIfOlder) 在这里,doNotDownloadIfOlder是一组自定义对象。
在一些测试用例中,它们的数量超过300。我怀疑这可能是错误消息查询筛选器超过值限制的原因: 250用于容器。
因此,我修改了代码:
let doNotDownloadIfOlderFormat = "NOT " + iCloudRecordKeyName + " IN %@"
let limit = min(doNotDownloadIfOlder.count, max)
let shortened = Set(Array(doNotDownloadIfOlder)[0 ..< limit])
let doNotDownloadIfOlderPredicate = NSPredicate.init(format: doNotDownloadIfOlderFormat, shortened) 其中,我将max设置为300以下的测试值。
其结果是:
显然,对于查询,可能存在一个无文档的服务器限制。这个奇怪的数字140可能与我的定制对象的大小有关。
先前的回答:
文档说:
服务器可以随时更改其限制,但以下是一般准则:
如果应用程序接收到CKError.Code.limitExceeded,则必须将操作拆分成两部分,然后再次尝试请求。
https://stackoverflow.com/questions/45346613
复制相似问题