即使在DispatchQueue.main.async Swift 3中设置后,数组仍然为空

时间:2016-10-23 02:42:12

标签: ios swift swift3 grand-central-dispatch

**编辑:重新措辞,因为数组不是零,但它没有设置任何值,它应该**

这里是代码:       var calendarArray:[Feed] = []

  override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code

    DispatchQueue.main.async {
      self.calendarArray = self.dataFetcher.getRSSFeed(withURL: NSLocalizedString("CALENDAR", comment: ""), andIsAnEvent: false) as! [Feed]
    }

    let customNib = UINib(nibName: "UpcomingDatesCustomCell", bundle: nil)
    datesTableView.register(customNib, forCellReuseIdentifier: "upcomingDatesCustomCell")
  }


  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = self.datesTableView.dequeueReusableCell(withIdentifier: "upcomingDatesCustomCell", for: indexPath) as! UpcomingDatesCustomCell

    // update ui based off what's stored in calendarArray

    return cell
  }

这是在awakeFromNib中发生的。

calendarArray中访问cellForRowAtIndexPath时,它超出范围......

这里发生了什么?

注意:我在主线程上运行异步,因为这是从在线提取的东西,我们有一个加载微调器。

2 个答案:

答案 0 :(得分:2)

你不应该从numberOfRowsInSection返回4。似乎在calendarArray有任何项目之前调用此方法,因此您的界限出错。你为什么特意选择4?如果您尝试在calendarArray中显示所有项目,请使用:

return calendarArray.count

此外,您可能不应该以这种方式使用数据填充数组。我在这里做出假设,但似乎您的dataFetcher.getRSSFeed方法执行同步网络请求,因为您已将其包装在DispatchQueue.main.async的调用中。这不会产生你想要的效果。通过这种方式调度,您可以有效地跳过一个运行循环,然后在主线程上运行代码。您应该调度到后台线程(而不是主线程)并在那里获取

您应该考虑使用NSURLSession发出异步请求。出于多种原因,在iOS中同步获取数据并不是一个好主意。

编辑:其他信息

答案 1 :(得分:1)

您的代码:

DispatchQueue.main.async {
    self.calendarArray = self.dataFetcher.getRSSFeed(withURL: NSLocalizedString("CALENDAR", comment: ""), andIsAnEvent: false) as! [Feed]
}

没有意义。你告诉编译器:“首先让我获得主线程,然后在后台线程中获取数据!”,这显然不会更新数组或UI。

这是您在进行多线程时应该做的事情:

DispatchQueue.global(attributes: [.qosDefault]).async { 
    // fetch data here  
    let contents = self.dataFetcher.getRSSFeed(withURL: NSLocalizedString("CALENDAR", comment: ""), andIsAnEvent: false)
    DispatchQueue.main.async(execute: { 
    // UI Updates
    self.calendarArray = contents
    self.tableView.reloadData()
    })
}

另外,正如@daltonclaybrook建议的那样,您还应该在calendarArray.count

中返回numberOfRowsInSection

我建议您将其放在viewDidLoad而不是awakeFromNib