4

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) {

}
Eric Aya
  • 68,765
  • 33
  • 165
  • 232
Jérémy
  • 363
  • 1
  • 2
  • 19

2 Answers2

2

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>)

Reinier Melian
  • 18,995
  • 3
  • 32
  • 51
  • Thanks for your example code. How do I get the unwind segue action to execute this method? In which func do I call this method? The `prepare` or the `shouldPerformSegue`? Or do I delete the unwind segue and create an IBOutlet to a method? – Jérémy Jan 02 '18 at 17:06
  • @Jérémy how are your triggering this unwind segue? – Reinier Melian Jan 02 '18 at 17:08
  • I just ctrl-dragged from the 'cancel' button to the exit responder. When a user clicks the button, the segue automatically unwinds. It shows the UIAlert only for a second, then the segue is performed. This is why I was trying to get it working with `shouldPerformSegue` – Jérémy Jan 02 '18 at 17:11
  • 1
    Well then connect your cancel button to the IBAction instead, and should work @Jérémy – Reinier Melian Jan 02 '18 at 17:12
  • 1
    Works! I removed the unwind segue that was linked to the cancel button and created a manual unwind segue. (ctrl-drag from view controller icon to the exit responder). Thanks for all your help! – Jérémy Jan 02 '18 at 17:34
1

First, make the alert with two options:

class ViewController: UIViewController {

    @IBAction func showAlertButtonTapped(_ sender: UIButton) {

        // create the alert
        let alert = UIAlertController(title: "UIAlertController", message: "Save this work?", preferredStyle: UIAlertControllerStyle.alert)

        // add the actions (buttons)
        alert.addAction(UIAlertAction(title: "Hell Yeah", style: UIAlertActionStyle.default, handler: nil))
        alert.addAction(UIAlertAction(title: "Hell No", style: UIAlertActionStyle.cancel, handler: nil))

        // show the alert
        self.present(alert, animated: true, completion: nil)
    }

After this, you have to make the segue and then name it (also connect it by control dragging from the view controller yellow icon to the other view controller):

enter image description here

After that put this your code to execute the segue:

self.performSegue(withIdentifier: ":)", sender: self)

After that you are going to execute the segue when the user responds to the alert:

if buttonTitle == "Hell Yeah" {
    elf.performSegue(withIdentifier: ":)", sender: self)
}

so, in the end, your code should look like this:

 class ViewController: UIViewController {

    @IBAction func showAlertButtonTapped(_ sender: UIButton) { 
        // create the alert
        let alert = UIAlertController(title: "UIAlertController", message: "Save this work?", preferredStyle: UIAlertControllerStyle.alert)

        // add the actions (buttons)
        alert.addAction(UIAlertAction(title: "Hell Yeah", style: UIAlertActionStyle.default, handler: nil))

        alert.addAction(UIAlertAction(title: "Hell No", style: UIAlertActionStyle.cancel, handler: nil))

        // show the alert
        self.present(alert, animated: true, completion: nil)

        if buttonTitle == "Hell Yeah" {
            self.performSegue(withIdentifier: ":)", sender: self)
        }

    }
}
Xcoder
  • 1,374
  • 3
  • 15
  • 29
Hamza
  • 616
  • 7
  • 22
  • IM only 13 years old so if I failed answering please don't downvote or be harsh just let me know and ill change it. – Hamza Jan 02 '18 at 17:08
  • 1
    The `UIAlertAction` have now a handler closure, there you can do whatever you need after the action is touched, you don't need to compare by the `UIAlertButton` title, but if you are only 13 years old, men you are a great prospect!!!, I think is awesome having a kid of 13 years answering SO question, that rocks!!! – Reinier Melian Jan 02 '18 at 17:14
  • @Hamza I think by "Segway" you meant "segue"? – Xcoder Jan 02 '18 at 17:42
  • Thanks for your help and respect for the fact that you're only 13 years old :) – Jérémy Jan 03 '18 at 22:24