1

是否可以在 cloudkit 中实现“批量提取”,以便我可以调用一个方法来提取下一条 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)
}
4

2 回答 2

3

您应该使用所需的值而不是常量值设置结果限制。CKQueryOperationMaximumResults

我的建议是定义一个带有结果参数的完成处理程序CKRecordCKQueryCursor. 必须在queryCompletionBlockCKQueryOperation 的处理程序中调用此完成处理程序。

一旦你的处理程序被调用,你就可以处理结果,如果光标不为空,则意味着有更多的结果要获取。

可能是这样的

// 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 条记录。

于 2018-02-27T09:43:09.737 回答
0

所以@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)
}
于 2020-11-21T21:54:43.210 回答