使用 cloudkit ckqueryoperation 批量获取
batch fetching with cloudkit ckqueryoperation
是否可以在 cloudkit 中实现 'batch fetching',以便我可以调用一个方法来提取下一个 X 记录?目前,根据 CloudKit Batch Fetches? cloudkit 隐式处理此问题,但我想以某种方式创建一种方法,允许我每次提取指定数量的查询。
这是我目前所拥有的:(其中 continuePullPosts 是与我发布的方法类似的方法)
queryOP.recordFetchedBlock = { record in
//do stuff here
annotations.append(postToAdd)
}
queryOP.queryCompletionBlock = { [unowned self] (cursor, error) in
DispatchQueue.main.async {
if error == nil {
if completionHandler(annotations) {
if cursor != nil {
let newQueryOP = CKQueryOperation(cursor: cursor!)
self.continuePullPosts(curLocation: curLocation, queryOP: newQueryOP,
annotations: annotations, completionHandler: completionHandler)
}
}
} else {
print(error)
print("could not pull posts")
}
}
}
queryOP.resultsLimit = CKQueryOperationMaximumResults
CKContainer.default().publicCloudDatabase.add(queryOP)
}
您应该将 result limit 设置为您想要的值而不是 CKQueryOperationMaximumResults
常数值。
我的建议是定义一个 完成处理程序 ,其参数用于 CKRecord
结果和 CKQueryCursor
。必须在 CKQueryOperation 的 queryCompletionBlock
处理程序中调用此完成处理程序。
调用处理程序后,您就可以处理结果,如果游标不为空,则意味着有更多结果要获取。
可能是这样的
// Completion Handler (closure) definition
public typealias YourFetchCompletionHandler = (_ records: [CKRecords]?, cursor: CKQueryCursor?) -> (Void)
这里是获取记录的函数
public func fetchYourRecords(_ cursor: CKQueryCursor? = nil, completionHandler handler: @escaping YourFetchCompletionHandler) -> Void
{
var result: [CKRecord] = [CKRecord]()
let queryOP: CKQueryOperation
if let cursor = cursor
{
// Operation to fetch another 10 records.
queryOP = CKQueryOperation(cursor: cursor)
}
else
{
// Create the operation for the first time
queryOP = CKQueryCursor(query:...)
}
queryOp.recordFetchedBlock = { (record: CKRecord) -> Void in
result.append(record)
}
queryOP.queryCompletionBlock = { [unowned self] (cursor, error) in
handler(result, cursor)
}
// Fetch only 10 records
queryOP.resultsLimit = 10
CKContainer.default().publicCloudDatabase.add(queryOP)
}
调用此函数后,您可以将闭包中返回的游标保存在一个变量中,如果它不是 nil,则再次调用该函数以恢复接下来的 10 条记录。
@Adolfo 的回答让我完成了 95%,但我遇到了一个问题:
每次我到达最后一页(或最后一批)或数据时,它都会从我的数据集的开头开始向我发送数据。
这是个问题,因为在我 运行 没有数据后,我想停止加载。
为了解决这个问题,我添加了一个参数来指定它是否是第一次提取。这允许我只在第一次获取时创建一个新查询。如果不是第一次获取,则不会进行新的查询并返回一个空数组。
public func fetchYourRecords(isFirstFetch: Bool, _ cursor: CKQueryCursor? = nil, completionHandler handler: @escaping YourFetchCompletionHandler) -> Void {
var result: [CKRecord] = [CKRecord]()
let queryOP: CKQueryOperation
if isFirstFetch {
// Create the operation for the first time
queryOP = CKQueryCursor(query:...)
} else if let cursor = cursor {
// Operation to fetch another 10 records.
queryOP = CKQueryOperation(cursor: cursor)
} else {
// If not first time and if cursor is nil (which means
// there is no more data) then return empty array
// or whatever you want
handler([], nil)
return
}
queryOp.recordFetchedBlock = { (record: CKRecord) -> Void in
result.append(record)
}
queryOP.queryCompletionBlock = { [unowned self] (cursor, error) in
handler(result, cursor)
}
// Fetch only 10 records
queryOP.resultsLimit = 10
CKContainer.default().publicCloudDatabase.add(queryOP)
}
是否可以在 cloudkit 中实现 'batch fetching',以便我可以调用一个方法来提取下一个 X 记录?目前,根据 CloudKit Batch Fetches? cloudkit 隐式处理此问题,但我想以某种方式创建一种方法,允许我每次提取指定数量的查询。 这是我目前所拥有的:(其中 continuePullPosts 是与我发布的方法类似的方法)
queryOP.recordFetchedBlock = { record in
//do stuff here
annotations.append(postToAdd)
}
queryOP.queryCompletionBlock = { [unowned self] (cursor, error) in
DispatchQueue.main.async {
if error == nil {
if completionHandler(annotations) {
if cursor != nil {
let newQueryOP = CKQueryOperation(cursor: cursor!)
self.continuePullPosts(curLocation: curLocation, queryOP: newQueryOP,
annotations: annotations, completionHandler: completionHandler)
}
}
} else {
print(error)
print("could not pull posts")
}
}
}
queryOP.resultsLimit = CKQueryOperationMaximumResults
CKContainer.default().publicCloudDatabase.add(queryOP)
}
您应该将 result limit 设置为您想要的值而不是 CKQueryOperationMaximumResults
常数值。
我的建议是定义一个 完成处理程序 ,其参数用于 CKRecord
结果和 CKQueryCursor
。必须在 CKQueryOperation 的 queryCompletionBlock
处理程序中调用此完成处理程序。
调用处理程序后,您就可以处理结果,如果游标不为空,则意味着有更多结果要获取。
可能是这样的
// Completion Handler (closure) definition
public typealias YourFetchCompletionHandler = (_ records: [CKRecords]?, cursor: CKQueryCursor?) -> (Void)
这里是获取记录的函数
public func fetchYourRecords(_ cursor: CKQueryCursor? = nil, completionHandler handler: @escaping YourFetchCompletionHandler) -> Void
{
var result: [CKRecord] = [CKRecord]()
let queryOP: CKQueryOperation
if let cursor = cursor
{
// Operation to fetch another 10 records.
queryOP = CKQueryOperation(cursor: cursor)
}
else
{
// Create the operation for the first time
queryOP = CKQueryCursor(query:...)
}
queryOp.recordFetchedBlock = { (record: CKRecord) -> Void in
result.append(record)
}
queryOP.queryCompletionBlock = { [unowned self] (cursor, error) in
handler(result, cursor)
}
// Fetch only 10 records
queryOP.resultsLimit = 10
CKContainer.default().publicCloudDatabase.add(queryOP)
}
调用此函数后,您可以将闭包中返回的游标保存在一个变量中,如果它不是 nil,则再次调用该函数以恢复接下来的 10 条记录。
@Adolfo 的回答让我完成了 95%,但我遇到了一个问题:
每次我到达最后一页(或最后一批)或数据时,它都会从我的数据集的开头开始向我发送数据。
这是个问题,因为在我 运行 没有数据后,我想停止加载。
为了解决这个问题,我添加了一个参数来指定它是否是第一次提取。这允许我只在第一次获取时创建一个新查询。如果不是第一次获取,则不会进行新的查询并返回一个空数组。
public func fetchYourRecords(isFirstFetch: Bool, _ cursor: CKQueryCursor? = nil, completionHandler handler: @escaping YourFetchCompletionHandler) -> Void {
var result: [CKRecord] = [CKRecord]()
let queryOP: CKQueryOperation
if isFirstFetch {
// Create the operation for the first time
queryOP = CKQueryCursor(query:...)
} else if let cursor = cursor {
// Operation to fetch another 10 records.
queryOP = CKQueryOperation(cursor: cursor)
} else {
// If not first time and if cursor is nil (which means
// there is no more data) then return empty array
// or whatever you want
handler([], nil)
return
}
queryOp.recordFetchedBlock = { (record: CKRecord) -> Void in
result.append(record)
}
queryOP.queryCompletionBlock = { [unowned self] (cursor, error) in
handler(result, cursor)
}
// Fetch only 10 records
queryOP.resultsLimit = 10
CKContainer.default().publicCloudDatabase.add(queryOP)
}