简体   繁体   中英

Swift - How to present ViewController when tapping button in a custom AlertController

I am developing in Swift 2.3

I have an Utils class enabling me to create UIAlertController easily.

public class Utils {

    class func buildAlertInfo(withTitle title: String?, andMessage message: String?, withHandler handler: (UIAlertAction -> Void)?) -> UIAlertController {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
        alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: handler))

        return alertController
    }
}

It enables me to build AlertController with ease :

let alert = Utils.buildAlertInfo(withTitle: "Information", andMessage: "John Snow is dying", withHandler: nil)
self.presentViewController(alert, animated: false, completion: nil)

My issue now is that I want to create an other type of custom Alert in my Utils Class. For example an Alert with a Button that navigates the user to a specific ViewController.

I don't know how can I access a ViewController in a Custom Class. Maybe pass as a parameter the ViewController I want to present after the Button is tapped ?

Should I respect the MVC pattern and not interact with the View in my Utils Class ?

EDIT :

The Alert I want should looks like this :

class func buildAlertInfoWithFavButton(withTitle title: String?, andMessage message: String?, withHandler handler: (UIAlertAction -> Void)?) -> UIAlertController {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
        alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: handler))
        alertController.addAction(UIAlertAction(title: "Favorite", style: UIAlertActionStyle.Default, handler: handler))

        return alertController
    }

Where the OK action is the same, but the Favorite action should navigates you to the FavoriteViewController.

What about

let alert = Utils.buildAlertInfo(
  withTitle: "Information",
  andMessage: "John Snow is dying",
  withHandler: { action in self.go(to: specificViewController) }
)
self.presentViewController(alert, animated: false, completion: nil)

?

You can still use your buildAlertInfo function and can pass handler function like this way.

//Add function in your controller
func handler(action: UIAlertAction) {
    //Add code of present
}

Now pass this function with your handler block

let alert = Utils.buildAlertInfo(withTitle: "Information", 
                                andMessage: "John Snow is dying",
                               withHandler: self.handler)

**Edit:**For multiple action you can create array of handler with your method like this.

func buildAlertInfoWithFavButton(withTitle title: String?, andMessage message: String?, withHandler handler: [((UIAlertAction) -> Void)]?) -> UIAlertController {

    alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: handler.first))
    alertController.addAction(UIAlertAction(title: "Favorite", style: UIAlertActionStyle.Default, handler: handler.last))
}

//Ok handler
func okHandler(action: UIAlertAction) {
    //Add code of present
}

//Favorite handler
func favoriteHandler(action: UIAlertAction) {
    //Add code of present
}

Now call the function like this.

let alert = Utils.buildAlertInfo(withTitle: "Information", 
                                andMessage: "John Snow is dying",
                               withHandler: [okHandler, favoriteHandler])

To be more Specific and use that method in any class of project. For this make a function in NSObject class. Like:

open  class func showAlert(_ delegate: UIViewController, message: String ,strtitle: String, handler:((UIAlertAction) -> Void)! = nil)
    {
        let alert = UIAlertController(title: strtitle, message: message, preferredStyle: UIAlertControllerStyle.alert)

        if handler == nil{
            alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))

        }
        else
        {
            alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: handler))
        }

        delegate.present(alert, animated: true, completion: nil)
    }

In Controller I will call the method and do the required work like:

 Alert.showAlert(self, message: "Message", strtitle: "Tittle!!", handler: {
                        (action : UIAlertAction) in
                  //Do your Work here
                })

Note: Here Alert is name of NSObject class.

I would suggest using segue identifiers as the passed parameter (make sure you reference a segue that starts in the ViewController you call the "buildAlert" function from).

public class Utils {

class func buildAlertInfo(withTitle title: String?, andMessage message: String?, withSegue segueIdentifier: String?, sender: Any?) -> UIAlertController {
    let alertController = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
    alertController.addAction(UIAlertAction(title: "OK", style: .Default, handler: handler: {
                action in
                self.performSegue(withIdentifier: segueIdentifier, sender: sender)
            })

    return alertController
}

This can also be achieved without creating a new function, just sending the handler part from above as a parameter to the function you already have, like this:

let alert = Utils.buildAlertInfo(withTitle: "Information", andMessage: "John Snow is dying", withHandler: {
                action in
                self.performSegue(withIdentifier: "mySegueIdentifier", sender: self)
            })

EDIT: Note that the sender part can be any object that has an @IBOutlet reference in the ViewController the function call takes place

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM