【问题标题】:Custom UICollectionView Data Source and Delegate自定义 UICollectionView 数据源和委托
【发布时间】:2025-12-21 06:25:12
【问题描述】:

我已经为此苦苦挣扎了好几个小时,因为我对 XCode 和 Swift 还比较陌生。

我的故事板中有一个CollectionView,并且想将其数据源和委托方法链接到我的ViewController 之外的单独类,但它不起作用。 有人可以帮忙吗?

override func viewDidLoad() {
    super.viewDidLoad()

    //
    self.card.center = CGPoint(x: self.view.center.x, y: self.view.center.y)

    self.card.layer.cornerRadius = 5

    self.card.layer.shadowOpacity = 0.1

    //

    self.card2.center = CGPoint(x: self.view.center.x, y: self.view.center.y)

    self.card2.layer.cornerRadius = 5

    self.card2.layer.shadowOpacity = 0.1

    //

    self.view.bringSubview(toFront: self.card)

    // HERE IS THE LINK

    setDS()

    collectionView.reloadData()
    // ----------------------




}

private func setDS() {

    let dataSourceAndDelegate = CollectionViewController()

    collectionView.dataSource = dataSourceAndDelegate
    collectionView.delegate = dataSourceAndDelegate


}


import UIKit

private let reuseIdentifier = "Cell"

class CollectionViewController: UICollectionViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.backgroundColor = UIColor.red

        print("View did load")


        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false

        // Register cell classes
        self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)


        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    /*
     // MARK: - Navigation

     // In a storyboard-based application, you will often want to do a little preparation before navigation
     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
     // Get the new view controller using [segue destinationViewController].
     // Pass the selected object to the new view controller.
     }
     */

    // MARK: UICollectionViewDataSource

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of items
        return 3
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)

        // Configure the cell
        cell.backgroundColor = UIColor.blue

        return cell
    }



    // MARK: UICollectionViewDelegate


    // Uncomment this method to specify if the specified item should be highlighted during tracking
    override func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool {
        return true
    }



    // Uncomment this method to specify if the specified item should be selected
    override func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
        return true
    }



    // Uncomment these methods to specify if an action menu should be displayed for the specified item, and react to actions performed on the item
    override func collectionView(_ collectionView: UICollectionView, shouldShowMenuForItemAt indexPath: IndexPath) -> Bool {
        return false
    }

    override func collectionView(_ collectionView: UICollectionView, canPerformAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
        return false
    }

    override func collectionView(_ collectionView: UICollectionView, performAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) {

    }


}

【问题讨论】:

  • 使用自定义类代替UICollectionViewController 并实现 UICollectionView 数据源协议和 UICollectionView 委托协议

标签: ios swift xcode uicollectionview


【解决方案1】:

不要使用UICollectionViewController 的子类作为自定义collectionview 的数据源和委托。

改为使用简单的 NSObject 类。这样,您只需要实现数据源和委托方法,而不必担心 UIViewcontroller 的视图方法(无论如何您都不需要它们)。

但即使您提供UICollectionViewController 的对象,它也应该可以工作。它不起作用,因为您没有在 ViewController 类中保留该对象并且它正在自动释放。 UICollectionView 不保留委托和数据源以防止保留循环。

let dataSourceAndDelegate = CollectionViewController()

dataSourceAndDelegate 设为存储属性。

此外,您需要在 ViewController 类中注册您的单元格(因为它具有您正在使用的集合视图)。请记住UICollectionViewController 中的collectionView 属性与ViewController 中的collectionView 不同。它是一个存储属性,因为UICollectionViewController 带有一个集合视图。

private let reuseIdentifier = "Cell"

class ViewController: UIViewController {
    let dataSourceAndDelegate = CollectionViewController()
    @IBOutlet var collectionView:UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.setDS()
        collectionView.reloadData()

    }


    private func setDS() {
        // Register cell classes
        self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)

        collectionView.dataSource = dataSourceAndDelegate
        collectionView.delegate = dataSourceAndDelegate

    }

}

【讨论】:

  • 非常感谢。 dataSourceAndDelegate 不是存储属性是问题所在。非常感谢!