3

I have conformed the protocols UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UIScrollViewDelegate to a seperate class named CollectionViewWeekDelegate but the delegate methods such as didSelectItemAt is not getting called.

I'm also setting the delegate to CollectionView in viewDidLoad()

Please find the code below:

Delegate Class

class CollectionViewWeekDelegate: NSObject, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UIScrollViewDelegate {

    internal var parent: EarningsViewController?

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

        parent?.weekTabSelectedPosition = indexPath.item

        let indexPathh = IndexPath(item: indexPath.item, section: 0)

        parent?.collectionViewSchedule.scrollToItem(at: indexPathh, at: .right, animated: true)
        parent?.collectionViewWeeks.scrollToItem(at: indexPath, at: .top, animated: true)

        parent?.collectionViewWeeks.reloadData()

    }


    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

        let offsetX = parent?.collectionViewSchedule.contentOffset.x
        let contentWidth = parent?.collectionViewSchedule.bounds.width

        let page = Int(offsetX! / contentWidth!)

        parent?.weekTabSelectedPosition = page



        var earningsText  = "\("grossEarnings".localize()) $\(String(format: "%0.2f", 0.0))"

        if let earnings = parent?.schedules?[page].grossWeekSalary{
            earningsText = "\("grossEarnings".localize()) $\(String(format: "%0.2f", earnings))"


            parent?.buttonGrossEarnings.setTitle(earningsText, for: .normal)

            parent?.collectionViewWeeks.selectItem(at: IndexPath(item: page, section: 0), animated: true, scrollPosition: .centeredHorizontally)}
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        if collectionView.tag == 2{
            return CGSize(width: UIScreen.main.bounds.width, height: (parent?.collectionViewSchedule.bounds.height)!)
        }else{
            return CGSize(width: 150, height: 50)
        }
    }
}

viewDidLoad function where the CollectionView delegate is being assigned:

override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationController?.title = "schedule".localize()

    self.navigationItem.leftBarButtonItem = super.getMenuBartItem()

    if let flowLayout = collectionViewWeeks.collectionViewLayout as? UICollectionViewFlowLayout{
        flowLayout.estimatedItemSize = CGSize(width: 150, height: 50)
    }

    if let collectionFlowLayout = collectionViewSchedule.collectionViewLayout as? UICollectionViewFlowLayout{
        collectionFlowLayout.minimumLineSpacing = 0
        collectionFlowLayout.minimumInteritemSpacing = 0

    }

    let weekDelegate = CollectionViewWeekDelegate()
    weekDelegate.parent = self

    collectionViewWeeks.delegate = weekDelegate
    collectionViewSchedule.delegate = self

    collectionViewWeeks.reloadData()
}
Arasuvel
  • 2,971
  • 1
  • 25
  • 40
Akshay Sood
  • 6,366
  • 10
  • 36
  • 59

2 Answers2

6

Your weekDelegate gets deallocated when viewDidLoad finishes execution - you don't keep a strong reference to it, only the local variable. The only other class holding a reference to it is the UICollectionView itself (in your case collectionViewWeeks), but UICollectionView define its delegate as weak.

Just do this to keep the reference alive:

// create a strong property and use it instead of local variable
fileprivate let weekDelegate = CollectionViewWeekDelegate()

override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationController?.title = "schedule".localize()

    self.navigationItem.leftBarButtonItem = super.getMenuBartItem()

    if let flowLayout = collectionViewWeeks.collectionViewLayout as? UICollectionViewFlowLayout{
        flowLayout.estimatedItemSize = CGSize(width: 150, height: 50)
    }

    if let collectionFlowLayout = collectionViewSchedule.collectionViewLayout as? UICollectionViewFlowLayout{
        collectionFlowLayout.minimumLineSpacing = 0
        collectionFlowLayout.minimumInteritemSpacing = 0

    }

    weekDelegate.parent = self

    collectionViewWeeks.delegate = weekDelegate
    collectionViewSchedule.delegate = self

    collectionViewWeeks.reloadData()
}
Milan Nosáľ
  • 19,169
  • 4
  • 55
  • 90
  • @MilanNosal: AkshaySood stated before (see my comment to the question) that the delegate is not weakly referenced. – Andreas Oetjen Jan 25 '18 at 08:33
  • @AndreasOetjen in his code, the only reference to that delegate is his **local variable**.. the only other reference we can see there is a `UICollectionView.delegate`, and that **is** a `weak` reference.. so I bet that is the problem.. unless he shows us where the `strong` reference is defined, I have to assume this is the problem – Milan Nosáľ Jan 25 '18 at 08:35
  • @MilanNosal: I strongly agree with you, and this also was my first thought, but undoubtfully he answered my question before that _it is not weak_ – Andreas Oetjen Jan 25 '18 at 08:37
  • 1
    @AndreasOetjen In 99% of the time, the code is a better description of the situation than author's assumptions about the code (and I am talking about my own experiences as well).. let him try my suggestion and we will see what happens – Milan Nosáľ Jan 25 '18 at 08:39
  • @AkshaySood glad to help – Milan Nosáľ Jan 25 '18 at 09:08
-1

You can set DataSource and Delegate to self in Cell awakeFromNib method and do the cell registration. It will fix the delegate not getting called issue. Because currently when your cell is getting dequeued at that time your passing the data to show but inner collection view instance is nil thats why its not calling the delegate method.

you can try like this.

    class CustomCollectionViewCell: UICollectionViewCell {
    
    @IBOutlet weak var collectionView: UICollectionView!
    
    private let cellId = "CollectionViewCellID"
       
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        collectionView.delegate = self;
        collectionView.dataSource = self;
        collectionView.register(UINib(nibName: cellId, bundle: nil), forCellWithReuseIdentifier: cellId)
    }
}
Abhishek B
  • 157
  • 8