iosswiftuicollectionviewcellnibuipopoverpresentationcontroller

How to present a popoverPresentationController from custom UICollectionViewCell NIB


I have a popover that was defined in a UIViewController, but now needs to be presented from a custom UICollectionViewCell. The present is no longer working as the class is a UICollectionViewCell and no longer a UIViewController. How do I present the popover from the custom UICollectionViewCell.

   @IBAction func period(_ sender: Any) {

        let storyboard = UIStoryboard(name: "ScoreClockPopoverViewController", bundle: nil)
        let scoreClockPopoverViewController = storyboard.instantiateViewController(withIdentifier: "ScoreClockPopoverViewController") as! ScoreClockPopoverViewController

        scoreClockPopoverViewController.modalPresentationStyle = .popover

        let popover = scoreClockPopoverViewController.popoverPresentationController!
        popover.delegate = self
        popover.permittedArrowDirections = .any
        popover.sourceView = periodButton
        popover.sourceRect = periodButton.bounds


        present(scoreClockPopoverViewController, animated: true, completion:nil)
       //Error: Use of unresolved identifier 'present'

    }

If I try to extend the UICollectionViewCell as a UIViewContoller I get the following error: Extension of type 'HeaderCollectionViewCell' cannot inherit from class 'UIViewController'


Solution

  • Set your CollectionViewcontroller as Delegate of your CollectionViewCell.

    When the period function on your CollectionViewCell is called, call the "didClickPeriod" function (that you create yourself) of the cell's delegate.

    Include this e.g. in your cell

    protocol HeaderCollectionViewCellDelegate {
        func didClickPeriod(sender: Any)
    }
    

    make sure the cell has a property

    var delegate: HeaderCollectionViewCellDelegate!
    

    Notice the !. Assuming you instantiate from Storyboard you can't pass your delegate on instantiation but have to fill it "manually". The ! basically states that you can work with this property as if it is always set - assuming you fill the property properly, this will save you from unwrapping all the time. If you don't, you'll receive a crash.

    In your period function simply do

    @IBAction func period(_ sender: Any) {
       self.delegate.didClickPeriod(sender)
    }
    

    In your CollectionViewController make sure it implements the protocol e.g. by including

    extension YourCollectionViewController: HeaderCollectionViewCellDelegate {
        func didClickPeriod(sender: Any) {
            // your previous presentation logic. 
            // But now you're in the CollectionViewController so you can do
           ...
           present(scoreClockPopoverViewController, animated: true, completion:nil)
    
        }
    }