Ios 无法在额外类中外包UICollectionViewDatasource

Ios 无法在额外类中外包UICollectionViewDatasource,ios,swift,uicollectionview,uikit,Ios,Swift,Uicollectionview,Uikit,我有一个带有CollectionView的ViewController,希望将UICollectionViewDataSource放入一个额外的类中,以便可以重用它。(我没有使用界面生成器) 因此,我创建了一个额外的类: class MyDataSource: NSObject, UICollectionViewDelegate, UICollectionViewDataSource { public func collectionView(_ collectionView:

我有一个带有CollectionView的ViewController,希望将UICollectionViewDataSource放入一个额外的类中,以便可以重用它。(我没有使用界面生成器)

因此,我创建了一个额外的类:

class MyDataSource:  NSObject, UICollectionViewDelegate, UICollectionViewDataSource {

        public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return 5
        }

        public func numberOfSections(in collectionView: UICollectionView) -> Int {
            return 1
        }

        public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MYIDENTIFIER", for: indexPath)
            cell.backgroundColor = .blue
            return cell
        }

}
在带有CollectionView的ViewController中,我将其设置为:

override func viewDidLoad() {
    super.viewDidLoad()

    collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "MYIDENTIFIER")

    let myDataSource = MyDataSource()
    collectionView.delegate = myDataSource
    collectionView.dataSource = myDataSource

}
但是,collectionView将保持为空-上面没有单元格

但是,如果我将所有数据源函数放入ViewController类本身,并将委托和数据源设置为self,那么一切都可以正常工作


是否无法将UICollectionViewDataSource外包到其他文件中,或者您还需要做其他事情?

谢谢您的帮助!我尝试了Galo的建议,但对我来说没有用。然而,我找到了解决办法:

您必须将代理初始化为ViewController的属性,并在其viewDidLoad函数中而不是!那么一切都正常了

let myDataSource = MyDataSource()
override func viewDidLoad() {
    super.viewDidLoad()

    collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "MYIDENTIFIER")

    collectionView.delegate = myDataSource
    collectionView.dataSource = myDataSource

}

以防万一。这就是我说调用init方法的原因@Andrey Chernukha,如果引起任何混乱,我很抱歉。这就是为什么我说它与
init
一起工作,但我想这与Pascal的原因是一样的

import UIKit

class ViewController: UIViewController {

    lazy var collectionView : UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.backgroundColor = .green
        return cv
    }()

    var dataSource : CustomDataSource!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.view.addSubview(collectionView)
        collectionView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
        dataSource = CustomDataSource(collectionView: collectionView)
    }

}

class CustomDataSource : NSObject, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate {

    let collectionView : UICollectionView

    init(collectionView: UICollectionView) {
        self.collectionView = collectionView
        super.init()
        self.collectionView.dataSource = self
        self.collectionView.delegate = self
        self.collectionView.register(Cell.self, forCellWithReuseIdentifier: "cell")
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 3
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        cell.backgroundColor = .red
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: 100, height: 100)
    }

}


class Cell : UICollectionViewCell {

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }

    func setupViews() {
        self.backgroundColor = .red
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

我对它进行了测试,原因是,
dataSource
在collectionView中很弱,因此如果在
viewDidLoad()

中声明,则在实例化后会立即释放它。这是另一个经常被忽略的范围问题

  override func viewDidLoad() {
super.viewDidLoad()

collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "MYIDENTIFIER")

let myDataSource = MyDataSource(). //See the problem here?
collectionView.delegate = myDataSource
collectionView.dataSource = myDataSource

} //myDataSource will be released!

我认为您必须使用collectionView初始化数据源。在数据源中创建一个
init(collectionView:UICollectionView)
initclass@GaloTorresSevilla它应该如何帮助呢?@AndreyChernukha它将使用collectionView初始化数据源。然后在dataSource类中设置
collectionView.dataSource=self
。“我是这样做的,而且很管用。”Galotorrensevilla说,“那么,你所做的和你所建议的之间的实际区别是什么?集合视图以任何一种方式接收数据源都不确定。这就是为什么我说我想。不过我会尽力弄清楚的