简体   繁体   English

使用 cloudkit ckqueryoperation 批量获取

[英]batch fetching with cloudkit ckqueryoperation

Is it possible to implement 'batch fetching' in cloudkit, so that i can call a method to pull the next X records?是否可以在 cloudkit 中实现“批量提取”,以便我可以调用一种方法来提取下一条 X 记录? Currently, according to CloudKit Batch Fetches?目前,根据CloudKit Batch Fetches? cloudkit handles this implicitly, but I would like to somehow create a method that allows me to pull a specified number of queries each time. cloudkit 隐式地​​处理这个问题,但我想以某种方式创建一个方法,允许我每次提取指定数量的查询。 Heres what I have so far: (where continuePullPosts is a similar method to the one i posted)这是我到目前为止所拥有的:(其中 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)
}

You should set the result limit with your desired value instead of CKQueryOperationMaximumResults constant value.您应该使用您想要的值而不是CKQueryOperationMaximumResults常量值设置结果限制

My recomendation is define a completion handler with parameters for the CKRecord results and the CKQueryCursor .我的建议是定义一个完成处理程序,其中CKRecord结果和CKQueryCursor This completion handler must be invoked in the queryCompletionBlock handler of your CKQueryOperation.必须在queryCompletionBlock处理程序中调用此完成处理程序。

Once your handler is invoked you can process the results, and if the cursor is not null means that there are more results to fetch.一旦您的处理程序被调用,您就可以处理结果,如果游标不为空,则意味着有更多的结果要获取。

It could be something like that它可能是这样的

// Completion Handler (closure) definition
public typealias YourFetchCompletionHandler = (_ records: [CKRecords]?, cursor: CKQueryCursor?) -> (Void)

And here the function where you fetch records这里是你获取记录的函数

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)
}

Once you invoke this function you can save the cursor returned in the closure in a variable, if it's not nil, to call once again the function to recover the next 10 records.调用此函数后,您可以将闭包中返回的游标保存在变量中,如果它不是 nil,则再次调用该函数以恢复接下来的 10 条记录。

So @Adolfo's answer got me 95% of the way, but I had one issue:所以@Adolfo 的回答让我成功了 95%,但我遇到了一个问题:

Every time I would reach the last page (or batch) or data, it just started sending me data from the beginning of my data set.每次我到达最后一页(或批次)或数据时,它都会从数据集的开头开始向我发送数据。

This was a problem because after I ran out of data, I wanted the loading to stop.这是一个问题,因为在我用完数据后,我希望停止加载。

To fix this, I added an argument to specify if it was the first fetch or not.为了解决这个问题,我添加了一个参数来指定它是否是第一次提取。 This allowed me to only create a new query when it was the first fetch.这允许我只在第一次获取时创建一个新查询。 If it wasn't the first fetch, no new query would be made and an empty array would be returned.如果它不是第一次获取,则不会进行新查询并返回一个空数组。

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)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM