【问题标题】:Custom Delegate & DataSource NSObjects best practice自定义委托和数据源 NSObjects 最佳实践
【发布时间】:2019-08-14 22:05:22
【问题描述】:

所以考虑这种情况,我有一个 UIViewController,其中包含一个简单的 UICollectionView,但 Delegate & DataSource 协议与 NSObjectUIViewController 是分开的。

看起来像这样

class MainCollctionViewDelegate: NSObject, UICollectionViewDelegate
class MainCollectionViewDataSrouce: NSObject, UICollectionViewDataSource

我在我的UIViewController 中使用它们,就像这样,

lazy var CVDelegate = MainCollctionViewDelegate()
lazy var CVDataSource = MainCollectionViewDataSrouce()
//MARK: - Life Cycle
override func viewDidLoad() {
    super.viewDidLoad()
    collectionView.registerCell(PlainCell.self) // register custom cell Nib into collection View.
    collectionView.delegate = CVDelegate //Set Deleagte
    collectionView.dataSource = CVDataSource // Set data Source
}

这种方法将来会导致任何内存泄漏吗?考虑到我将实施注入来填充CollectionView 的数据源,将来会是这样的。

 MainCollectionViewDataSrouce(with: Foo) // Foo is some data to populate the collection with. 

对此有更好的做法吗?考虑到我正在努力实现 最少的代码编写(冗余)。

注意:这也适用于UITableViewDelegate & UITableViewDataSource

【问题讨论】:

  • 我已经在仪器中测试过,仍然没有问题,但测试只在一个 UIViewController 上,我需要最终的测试用例,或者如果有人之前已经使用过这种方法可以建议
  • 我最近也在做同样的事情。我认为这不会产生任何内存泄漏,只需关注分析器/图表即可。但是,如果您只使用一次,那么绝对不需要这种架构。
  • @MauricioChirino 我同意,我正在考虑这个未来,因为我可能会多次使用它,如图所示,我最终会用数据注入数据源,所以我可以在我的应用程序中使用它非常快,没有一遍又一遍地写入相同数据源的开销。
  • @MauricioChirino 也想象用这种方法进行单元测试,我认为可能真的很好
  • "这种方法将来会导致内存泄漏吗?"默认情况下不会,除非你做了导致保留周期的事情。

标签: ios swift memory-management


【解决方案1】:

这种方法将来会导致内存泄漏吗?

现在不行。
您的内存图将如下所示:

所以这里没有内存循环,也没有理由泄漏内存。

重要。如果您在 viewController 上添加来自 DataSource / Delegate 的引用,请确保它是弱引用,否则您将创建内存循环。

注意。您可以在 collectionView 上添加来自 DataSource / Delegate 的强引用,因为 collectionView 在 dataSource 和委托上具有弱引用。所以也没有循环

旁注

最好在数据源中注册单元格,因为“只有”数据源知道将使用什么类型的单元格。

【讨论】:

  • 一般来说,为数据源/委托使用单独的类是一个好方法。您甚至可以更进一步,创建适用于大多数表格/集合的通用变体
  • 你能给我一个链接来阅读你的意思的通用变体
  • @MohmmadS 试试谷歌swift generic uitableviewdatasource。这里有很多文章,我没有任何建议
【解决方案2】:

您的问题相当模糊,但总的来说,这是一种非常普遍的做法。我们公司经常使用这种模式:

class MainCollectionViewController: UIViewController {
    lazy var dataSource: UICollectionViewDataSource = self
    lazy var delegate: UICollectionViewDelegate = self

    static func with(dataSource: UICollectionViewDataSource, delegate: UICollectionViewDelegate) -> MainCollectionViewController {
        let vc = MainCollectionViewController()
        vc.dataSource = dataSource
        vc.delegate = delegate

        return vc
    }
}

extension MainCollectionViewController: UICollectionViewDataSource {
    // code
}

extension MainCollectionViewController: UICollectionViewDelegate {
    // code
}

两个主要用途是用于单元测试和将数据传递给视图控制器。测试人员可以在测试时注入自定义数据源和委托:

let testVC = MainCollectionViewController.with(dataSource: ..., delegate: ...)
// do test

或者传递数据给它:

// In another view controller
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destinationVC = segue.destination as? MainCollectionViewController {
        destinationVC.dataSource = ...
        destinationVC.delegate = ...
    }
}

关于内存泄漏,这种模式通常是安全的,但显然有人会偶尔遇到内存问题。您的里程可能会有所不同。

【讨论】:

  • 为什么 UIViewController 不是 NSObject
  • + 我猜这与我使用的不同,但是 +1 表示努力和想法
猜你喜欢
  • 2014-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-27
  • 2012-12-07
  • 1970-01-01
  • 2011-09-21
  • 1970-01-01
相关资源
最近更新 更多