【问题标题】:Can not outsource UICollectionViewDatasource in extra class不能在额外的类中外包 UICollectionViewDatasource
【发布时间】:2019-02-04 19:19:12
【问题描述】:

我有一个带有 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 将保持为空 - 上面没有单元格。

但是,如果我将所有 DataSource 函数放入 ViewController 类本身并将委托和 DataSource 设置为 self,那么一切正常。

是否不能将 UICollectionViewDataSource 外包到其他文件中,或者您还有什么需要做的吗?

【问题讨论】:

  • 我认为你必须用collectionView初始化数据源。在你的 dataSource 类中创建一个init(collectionView: UICollectionView) init
  • @GaloTorresSevilla 它应该如何提供帮助?
  • @AndreyChernukha 它将使用 collectionView 初始化数据源。然后在 dataSource 类中设置collectionView.dataSource = self。我就是这样做的,而且效果很好。
  • @GaloTorresSevilla 所做的与您的建议之间的实际区别是什么?无论哪种方式,集合视图都接收数据源
  • 真的不确定。这就是为什么我说我认为。我会试着找出答案

标签: ios swift uicollectionview uikit


【解决方案1】:

以防万一。这就是我所说的调用 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() 中声明,它会在实例化后立即解除分配

【讨论】:

    【解决方案2】:

    感谢您的帮助!我尝试了 Galo 的建议,但对我来说这不起作用。但是,我找到了解决方案:

    您必须将委托初始化为 ViewController 的属性,并且 不要 在其 viewDidLoad 函数中!然后一切正常!

    let myDataSource = MyDataSource()
    override func viewDidLoad() {
        super.viewDidLoad()
    
        collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "MYIDENTIFIER")
    
        collectionView.delegate = myDataSource
        collectionView.dataSource = myDataSource
    
    }
    

    【讨论】:

      【解决方案3】:

      这是另一个经常被忽视的范围问题。

        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!
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-20
        • 1970-01-01
        • 2017-03-10
        • 2022-11-03
        • 2020-12-04
        • 2022-08-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多