【问题标题】:Why do I have to retained a strong reference to the tableView datasource?为什么我必须保留对 tableView 数据源的强引用?
【发布时间】:2018-09-27 11:44:33
【问题描述】:

我注意到当我手动设置 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 属性上有一个描述:

充当表格视图的数据源的对象。数据 source 必须采用 UITableViewDataSource 协议。数据源 不保留。

我想知道这是否相关。

谢谢

【问题讨论】:

  • 是的,您的第一个示例中的dataSource 的范围在onNext 块内,当块完成时,该类被释放,因为没有人保留。在第二个例子中不再是这种情况了。控制器对它有很强的引用。此外,您应该在 onNext 块内使用 week self,以避免控制器的保留周期。

标签: ios swift


【解决方案1】:

在表格视图中,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 文档。

【讨论】:

    猜你喜欢
    • 2011-12-30
    • 1970-01-01
    • 1970-01-01
    • 2019-11-02
    • 1970-01-01
    • 1970-01-01
    • 2016-10-17
    • 2018-10-11
    • 1970-01-01
    相关资源
    最近更新 更多