2015-02-06 45 views
0

我正在尝试使用CloudKit制作一个简单的基于表格的应用程序,该应用程序允许您深入查找有关特定项目的更多信息。假设我的应用程序显示了位于主题公园内的商店目录,并按园区划分。嵌套的CloudKit查询和UITableView

在我的初始表格视图中,我能够获得ThemeParks列表。点击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) 
     } 
    }) 
} 

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

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

     return self.shops[section].count 
} 

...我得到一个“致命的错误:数组索引超出范围”错误,因为商店的第一阵列被下载,但随后numberOfRowsInSection被称为第二阵列,这还没有。那么我怎样才能知道getShopsFromCloud()何时完成,以及我在世界的哪个位置拨打tableView.reloadData()电话?

+0

那么,你需要看看GCD - 使用调度组。 – Shmidt 2015-02-06 21:22:54

+0

感谢您指点我正确的方向! – 2015-02-07 05:27:18

+0

查看本教程以了解其工作原理:http://www.raywenderlich.com/79150/grand-central-dispatch-tutorial-swift-part-2。在你的情况下,你需要创建一个将下载段的调度组,然后当它完成时,你将用行更新段并重新加载表视图。 – Shmidt 2015-02-07 09:21:14

回答

0

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

+0

这最终成为了像我这样的新手最容易理解的解决方案!谢谢。 – 2015-02-17 22:57:30

0

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