嵌套 CloudKit 查询和 UITableView
Posted
技术标签:
【中文标题】嵌套 CloudKit 查询和 UITableView【英文标题】:Nested CloudKit queries and UITableView 【发布时间】:2015-02-06 21:11:31 【问题描述】:我正在尝试使用CloudKit
制作一个简单的基于表格的应用程序,它允许您深入查找有关特定项目的更多信息。假设我的应用显示了位于主题公园内的商店目录,按公园的各个部分划分。
在我的初始表格视图中,我能够获得 ThemeParks 的列表。点击 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()
调用之前完成。因此,如果我在完成处理程序中为 getSectionsFromCloud 重新加载表视图,它将不会显示商店。但是,如果我在completionHandler
中为getShopsFromCloud
重新加载表视图,则每次执行查询时(每个部分执行一次),numberOfRowsInSection
也会为每个部分调用一次。所以如果我的numberOfRowsInSection
是这样的:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return self.shops[section].count
...我收到“致命错误:数组索引超出范围”错误,因为第一个商店数组已下载,但随后为第二个数组调用 numberOfRowsInSection
,但该数组尚不存在。那么我如何知道getShopsFromCloud()
何时结束以及我在世界上的哪个位置拨打tableView.reloadData()
电话?
【问题讨论】:
好吧,你需要看看 GCD - Using Dispatch Groups。 感谢您为我指明正确的方向! 查看本教程以了解其工作原理:raywenderlich.com/79150/…。在您的情况下,您需要创建一个将下载部分的调度组,然后在完成后,您将使用行更新部分并重新加载表视图。 【参考方案1】:尝试使用获取请求之间的依赖关系,并将它们添加到数据库对象(CKContainer.defaultContainer().publicDatabase().addOperation
)的队列中,而不是调用便捷方法
【讨论】:
对于像我这样的新手来说,这最终成为最容易理解的解决方案!谢谢。【参考方案2】:我认为解决此问题的最简单方法是在创建 self.sections 数组的同时创建 self.shops 数组。只需确保每个 self.shops 项目还包含一个空数组。这样计数将返回 0,因为尚未获取列表。在 getShopsFromCloud 中执行 reloaddata 是正确的方法。您必须知道您需要在主队列上执行 reloaddata。
【讨论】:
以上是关于嵌套 CloudKit 查询和 UITableView的主要内容,如果未能解决你的问题,请参考以下文章