Matt
Matt

Reputation: 89

Custom UICollectionView Data Source and Delegate

I've been struggling with this for hours as I'm relatively new to XCode and Swift.

I have a CollectionView in my storyboard and want to link its data source and delegate methods to a separate class other than my ViewController but it isn't working. Can anyone help?

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?) {

    }


}

Upvotes: 2

Views: 4057

Answers (1)

Puneet Sharma
Puneet Sharma

Reputation: 9484

Don't use subclass of UICollectionViewController as datasource and delegate of your custom collectionview.

Instead use simple NSObject class. That way you would need to implement only the datasource and delegate methods and dont have to worry about UIViewcontroller's view methods(you dont need them anyway).

But even if you provide object of UICollectionViewController it should work. It is not working because you have not retained the object in your ViewController class and it is getting autoreleased. UICollectionView does not retain delgeate and datasource to prevent retain cycles.

let dataSourceAndDelegate = CollectionViewController()

Make dataSourceAndDelegate a stored property.

Also, you would need to register your cell inside ViewController class (because it has the collection view you are working with). Remember collectionView property inside UICollectionViewController is not same as your collectionView in ViewController. It is a stored property because UICollectionViewController comes with a colectionview.

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

    }

}

Upvotes: 2

Related Questions