为什么我必须保留对tableView数据源的强引用?

时间:2018-09-27 11:44:34

标签: ios swift

我注意到,当我手动设置tableview数据源时,必须保留对其的强烈引用,否则,将不会调用cellForRowAt。 (请注意,numberOfRowsInSectionnumberOfSections被调用了

class YAExploreViewController: UIViewController {
      ...
      dataSourceSubject
               .subscribe(onNext: { dataSource in
                            // I'm not storing a strong reference to the dataSource, and cellForRowAt wouldn't get called
                            self.tableView.dataSource = dataSource
                            self.tableView.reloadData()
                        })
               .disposed(by: self.bag)
      ...
}

解决方案:

class YAExploreViewController: UIViewController {
      var exploreDataSource: YAExploreDataSource?

      ...
      dataSourceSubject
               .subscribe(onNext: { dataSource in
                            // I'm storing a strong reference to the dataSource, and cellForRowAt got called
                            self.dataSource = dataSource
                            self.tableView.dataSource = self.dataSource
                            self.tableView.reloadData()
                        })
               .disposed(by: self.bag)
      ...
}

我注意到tableView dataSource属性上有一个描述:

  

用作表视图的数据源的对象。数据   源必须采用UITableViewDataSource协议。数据来源   没有保留。

我想知道这是否相关。

谢谢

1 个答案:

答案 0 :(得分:0)

在表格视图中,dataSource属性遵循“委托模式”(在UIKit中广泛使用),这意味着它必须为weak,并且必须自己保留。

主要原因是,如果表视图强烈引用dataSource,则在许多情况下(例如,如果您的视图控制器是数据源)它可能会创建一个引用周期和内存泄漏。

class MyController: UIViewController {
  @IBOutlet var tableview: UITableView?

  override func viewDidLoad() {
    super.viewDidLoad()
    tableview?.dataSource = self
  }
}

extension MyController: UITableViewDataSource {
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 0
  }

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    return UITableViewCell(frame: .zero)
  }
}

如果dataSourcestrong引用,则将导致内存泄漏。

如果您想进一步了解Swift中的内存管理方式,请查看Automatic Reference Counting文档。