关闭等待来自 CloudKit 的数据

Closures for waiting data from CloudKit

我有一个包含一些数据的 CloudKit 数据库。通过按下按钮,我的应用程序应该检查数据库中是否存在某些数据。问题是所有进程在我的应用程序获得搜索结果之前就结束了。我发现这很有用 ,据说它使用闭包。

我试图遵循相同的结构,但 Swift 要求我提供参数,我很快就迷路了。

有人可以帮助我吗?感谢您的帮助

func reloadTable() {
    self.timePickerView.reloadAllComponents()
}

func getDataFromCloud(completionHandler: @escaping (_ records: [CKRecord]) -> Void) {
    print("I begin asking process")
    var listOfDates: [CKRecord] = []
    let predicate = NSPredicate(value: true)

    let query = CKQuery(recordType: "Riservazioni", predicate: predicate)
    let queryOperation = CKQueryOperation(query: query)
    queryOperation.resultsLimit = 20

    queryOperation.recordFetchedBlock = { record in
        listOfDates.append(record)
    }

    queryOperation.queryCompletionBlock = { cursor, error in
        if error != nil {
            print("error")
            print(error!.localizedDescription)
        } else {
            print("NO error")
            self.Array = listOfDates
            completionHandler(listOfDates)
        }
    }
}

var Array = [CKRecord]()

func generateHourArray() {
        print("generate array")
        for hour in disponibleHours {
            let instance = CKRecord(recordType: orderNumber+hour)

            if Array.contains(instance) {
                disponibleHours.remove(at: disponibleHours.index(of: hour)!)
            }
        }

}

func loadData() {
    timePickerView.reloadAllComponents()
    timePickerView.isHidden = false
}



@IBAction func checkDisponibility(_ sender: Any) {
    if self.timePickerView.isHidden == true {

        getDataFromCloud{ (records) in
            print("gotData")
            self.generateHourArray()
            self.loadData()
        }
        print(Array)

    }
}

我很难理解你的代码以及 CloudKit 元素适合它的地方,所以我将尝试给出一个通用的答案,希望它仍然对你有所帮助。

让我们从我们要调用的函数开始,以获取我们的 CloudKit 数据,假设我们正在获取人员列表。

func getPeople() {

}

到目前为止这已经很简单了,所以现在让我们添加 CloudKit 代码。

func getPeople() {

    var listOfPeople: [CKRecord] = [] // A place to store the items as we get them

    let query = CKQuery(recordType: "Person", predicate: NSPredicate(value: true))
    let queryOperation = CKQueryOperation(query: query)
    queryOperation.resultsLimit = 20

    // As we get each record, lets store them in the array
    queryOperation.recordFetchedBlock = { record in
        listOfPeople.append(record)
    }

    // Have another closure for when the download is complete
    queryOperation.queryCompletionBlock = { cursor, error in
        if error != nil {
            print(error!.localizedDescription)
        } else {
            // We are done, we will come back to this
        }
    }
}

现在我们有了人员名单,但我们想 return 一旦 CloudKit 完成。正如您所说的那样,我们想为此使用闭包。让我们在函数定义中添加一个。

func getPeople(completionHandler: @escaping (_ records: [CKRecord]) -> Void) {
    ...
}

上面添加了一个完成处理程序闭包。我们要传递给调用者的参数是记录,因此我们将其添加到定义中。我们不期望任何人响应我们的完成处理程序,因此我们期望 return 值为 Void。您可能需要此处的布尔值作为成功消息,但这完全取决于项目。

现在让我们把整个事情联系起来。在我说过我们会回来的那一行,您现在可以将评论替换为:

completionHandler(listOfPeople)

这会在 CloudKit 完成后立即将人员列表发送给呼叫者。我在下面展示了一个调用此函数的示例。

getPeople { (records) in
    // This code wont run until cloudkit is finished fetching the data!
}

需要注意的是,CloudKit API 在哪个线程上运行。如果它在后台线程上运行,那么回调也将在后台线程上运行 - 因此请确保您没有对完成处理程序进行任何 UI 更改(或将其移至主线程)。

您可以对此代码进行很多改进,并使其适应您自己的项目,但它应该给您一个开始。马上,Id image 您将想要将完成处理程序参数更改为 Bool 以显示数据是否存在。

如果您发现任何错误或需要更多帮助,请告诉我。