自定义委托和数据源NSObjects的最佳实践

问题描述 投票:3回答:2

所以考虑这种情况,我有一个UIViewController包含一个简单的UICollectionView,但Delegate & DataSource协议是从NSObject分离UIViewController

它看起来像这样

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. 

这有更好的做法吗?考虑到我试图实现最小代码编写(冗余)。

注意:这也适用于UITableViewDelegateUITableViewDataSource

ios swift memory-management
2个回答
1
投票

Is this approach going to cause any memory leaks in the future ?

不是现在。 你的记忆图看起来像:memory graph

所以这里没有内存周期,也没有泄漏内存的理由。

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

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

Side note

最好在数据源中注册单元,因为“仅”数据源知道将使用哪种类型的单元。


1
投票

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

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 = ...
    }
}

至于内存泄漏,这种模式通常是安全的,但显然有人会偶尔遇到内存问题。你的旅费可能会改变。

© www.soinside.com 2019 - 2024. All rights reserved.