Alert from UICollectionViewCell button?

Hello all:


I have a collectionview using a custom cell that has 2 buttons in each cell. I need to display an alert to the User when a button is tapped, and tried this:

@IBAction func testButton_Tapped(_ sender: Any)

{

print("Test Button tapped")

let alertController = UIAlertController(title: "Title", message: "Message", preferredStyle: .alert)

let defaultAction = UIAlertAction(title: "Close", style: .default, handler: nil)

alertController.addAction(defaultAction)

self.present(alertController, animated: true, completion: nil)

}


but I get an error: Value of type 'DeviceCell' has no member 'present'. Note the function works, I get the print statement.


The alert does work if I put it in the ViewController extension here:

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


but it only works then if I tap the Cell itself, not the button.


Any and all input is appreciated!


John.

Accepted Reply

As you found, there's no `present(_:animated:completion:)` method in `UICollectionViewCell` class.

You need a ViewController to show alert.


One way to solve this issue, is having a `viewContoller` property in the cell class:

class MyCell: UICollectionViewCell {
    //...
    
    weak var viewController: UIViewController?
    
    //...
    
    @IBAction func testButton_Tapped(_ sender: Any) {
      print("Test Button tapped")
      let alertController = UIAlertController(title: "Title", message: "Message", preferredStyle: .alert)
      let defaultAction = UIAlertAction(title: "Close", style: .default, handler: nil)
      alertController.addAction(defaultAction)
      viewController?.present(alertController, animated: true, completion: nil)
    }
    
    //...
}

You set the property in `collectionView(_:cellForItemAt:)` in your ViewController class:

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! MyCell
        //...
        cell.viewController = self
        return cell
    }

Replies

As you found, there's no `present(_:animated:completion:)` method in `UICollectionViewCell` class.

You need a ViewController to show alert.


One way to solve this issue, is having a `viewContoller` property in the cell class:

class MyCell: UICollectionViewCell {
    //...
    
    weak var viewController: UIViewController?
    
    //...
    
    @IBAction func testButton_Tapped(_ sender: Any) {
      print("Test Button tapped")
      let alertController = UIAlertController(title: "Title", message: "Message", preferredStyle: .alert)
      let defaultAction = UIAlertAction(title: "Close", style: .default, handler: nil)
      alertController.addAction(defaultAction)
      viewController?.present(alertController, animated: true, completion: nil)
    }
    
    //...
}

You set the property in `collectionView(_:cellForItemAt:)` in your ViewController class:

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! MyCell
        //...
        cell.viewController = self
        return cell
    }

Thanks *again*, worked like a charm!