UK4
UK4

Reputation: 470

Swift - UIAlert doesn't work in UICollectionViewCell

I am coding without storyboard and I'm having this issue now that I can't find a good solution.

So I'm trying to call UIAlert from UICollectionViewCell like below.

self.window?.rootViewController?.present(alert, animated: true, completion: nil)

This is what I found in stackoverflow and it works.

But when the ViewController which has the UICollectionViewCell is presented from the other ViewController by present(_:animated:completion:) like below, UIAlert doesn't get called.

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

Does anyone know the solution for this issue?

Upvotes: 0

Views: 299

Answers (3)

Glaphi
Glaphi

Reputation: 452

The fact that your cell is responsible for presenting an alert controller is not a good design, The cell should delegate this. Having said that, it is possible to get the view controller where the cell is in and present the alert controller using it:

extension UIView {
    var parentController: UIViewController? {
        var parentResponder: UIResponder? = self
        while parentResponder != nil {
            parentResponder = parentResponder!.next
            if let viewController = parentResponder as? UIViewController {
                return viewController
            }
        }
        return nil
    }
}

And in the place where you'd like to present the controller from the cell:

if let vc = cell.parentController {
    vc.present(// alert controller)
}

Upvotes: 1

Hunaid Hassan
Hunaid Hassan

Reputation: 742

You can only present from the top most view controller. I assume you are trying to present alert controller from rootViewController. That will not work if another viewController has been presented over it already. Which in your case is HomeController.

Present it over the HomeController using self.present() call. Not over the rootViewController

Upvotes: 0

Abhishek Thapliyal
Abhishek Thapliyal

Reputation: 3718

No, that will not work you need to implement delegate for that if you want to show alert on tapping action from cell

 protocol CollectionViewCellDelegate: class {
    func showAlert(_ cell: CollectionViewCell, _ message: String)
 }

 class CollectionViewCell: UICollectionViewCell {
    ...
    ....
    .....

    weak var delegate: CollectionViewCellDelegate?

   @IBAction func yourButtonAction(_ sender: UIButton) {
       self.delegate?.showAlert(self, "your message")
   }
}

in your viewController

the collection's cellforRow

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
     let cell = collectioView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell

     ....
     cell.delegate = self
     return cell
}

conform to delegate like

   extension YourClass: CollectionViewCellDelegate {

    func showAlert(_ cell: CollectionViewCell, _ message: String) {

       let alert = UIAlertController(title: "Alert Title", message: "Alert Message", style = .alert)
       alert.addAction(UIAlertAction(title: "title", style: .default, handler: nil)
       self.presentViewController(alert, animated: true, completion: nil)

    }
 }

Upvotes: 2

Related Questions