嵌套的CloudKit查询和UITableView

时间:2015-02-06 21:11:32

标签: ios uitableview swift cloudkit

我正在尝试使用CloudKit创建一个简单的基于表格的应用,它允许您深入查找有关特定项目的更多信息。假设我的应用程序显示了位于主题公园内的商店目录,按照公园的各个部分划分。

在我的初始表视图中,我能够获得ThemePark列表。点击主题公园可深入到另一个表视图,该视图具有公园每个部分的节标题标题。我能够查询与所选ThemePark匹配的CKReference的章节。当我试图获得与每个部分匹配的商店时,会出现问题。我不知道在重新加载表格视图之前如何等待商店全部下载。以下是我的视图控制器的一些示例代码:

func getSectionsFromCloud() {
    let cloudContainer = CKContainer.defaultContainer()
    let publicDatabase = CKContainer.defaultContainer().publicCloudDatabase
    let recordToMatch = CKReference(recordID: themePark.recordID, action: CKReferenceAction.DeleteSelf)
    let predicate = NSPredicate(format: "themeParkOwner == %@", recordToMatch)
    let query = CKQuery(recordType: "ThemeParkSection", predicate: predicate)
    let sort = NSSortDescriptor(key: "name", ascending: true)
    query.sortDescriptors = [sort]
    self.publicDatabase.performQuery(query, inZoneWithID: nil, completionHandler: {
        results, error in

        if error == nil {
            println("Successfully retrieved sections")
            self.sections = results as [CKRecord]
            for section in self.sections {
                self.getShopsFromCloud(section)
            }

        } else {
            println(error)
        }
    })
}

这是我的getShopsFromCloud功能:

func getShopsFromCloud(record:CKRecord) {
    let cloudContainer = CKContainer.defaultContainer()
    let publicDatabase = CKContainer.defaultContainer().publicCloudDatabase
    let recordToMatch = CKReference(recordID: record.recordID, action:CKReferenceAction.DeleteSelf)
    let predicate = NSPredicate(format: "sectionOwner == %@", recordToMatch)
    let query = CKQuery(recordType: "Shop", predicate: predicate)
    self.publicDatabase.performQuery(query, inZoneWithID: nil, completionHandler: {
            results, error in

        if error == nil {
            println("Successfully retrieved shops.")
            self.shops.append(results as [CKRecord])

        } else {
            println(error)
        }
    })
}

问题是,getSectionsFromCloud()在所有getShopsFromCloud()次调用之前完成。因此,如果我在completionHandler中为getSectionsFromCloud重新加载表视图,它将不会显示商店。但是,如果我在completionHandler中为getShopsFromCloud重新加载表格视图,则每次执行查询时(每个部分都会执行一次),numberOfRowsInSection也会为每个部分调用一次。如果我的numberOfRowsInSection是这样的话:

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return self.shops[section].count
}

...我收到“致命错误:数组索引超出范围”错误,因为下载了第一批商店,但是第二个数组调用了numberOfRowsInSection,但是还没有。那么我怎么知道getShopsFromCloud()何时结束以及我在世界的哪个地方tableView.reloadData()打电话?

2 个答案:

答案 0 :(得分:0)

我认为解决此问题的最简单方法是在创建self.sections数组的同时创建self.shops数组。只需确保每个self.shops项目还包含一个空数组。这样,计数将返回0,因为尚未提取列表。在getShopsFromCloud中执行reloaddata是正确的方法。您必须要注意,您需要在主队列上执行reloaddata。

答案 1 :(得分:0)

尝试使用获取请求之间的依赖关系并将它们添加到数据库对象的队列(CKContainer.defaultContainer().publicDatabase().addOperation),而不是调用方便方法