Search code examples
iosswiftsegueunwind-segue

Show UIAlert before unwinding segue


I'm trying to fire an alert that asks if you want to save or delete a draft after pressing cancel. I'm quite close, but I can't seem to get it right.

I'm unwinding from 'ReplyMailViewController'(ViewController A) to 'MailContentViewController'(ViewController B).

I added the following code in ViewController A to show the alert and 'hold' the segue perform:

override func shouldPerformSegue(withIdentifier identifier: String?, sender: Any?) -> Bool {
    if let ident = identifier {
        if ident == "cancelDraft" {

            let saveDraftActionHandler = { (action:UIAlertAction!) -> Void in
                NSLog("EXIT")
            }

            let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)

            let deleteDraftAction = UIAlertAction(title: "Delete Draft", style: .destructive, handler: nil)
            alertController.addAction(deleteDraftAction)
            let saveDraftAction = UIAlertAction(title: "Save Draft", style: .default, handler: saveDraftActionHandler)
            alertController.addAction(saveDraftAction)
            let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
            alertController.addAction(cancelAction)

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

            return false
        }
    }
    return true
}

The segue holds with this code, but the issue is that I can't figure out how to continue the unwind segue after pressing 'Save Draft' for example.

I also have an unwind function in View Controller B, but I can't seem to figure out how I can use this one for this task:

@IBAction func cancelToMailContentViewController(_ segue: UIStoryboardSegue) {

}

Solution

  • Instead of perform the segue directly you need to show your UIAlertViewController first and according to the user response execute your segue or not

    @IBAction func showAlertViewController(){
        let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
    
        let replyAction = UIAlertAction(title: "Delete Draft", style: .destructive, handler: nil)
    
        let replyAllAction = UIAlertAction(title: "Save Draft", style: .default) { (action) in
            //Do whatever you need here
        }
    
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (action) in
            self.performSegue(withIdentifier: "cancelDraft", sender: action) //executing the segue on cancel
        }
        alertController.addAction(replyAllAction)
        alertController.addAction(replyAction)
        alertController.addAction(cancelAction)
        present(alertController, animated: true, completion: nil)
    
    }
    

    After this you only need to change the unwind segue action to execute this method, and your segue will be executed if you press cancel in the UIAlertViewController via self.performSegue(withIdentifier: #<SegueIdentifier>, sender: #<sender>)