Search code examples
iosswiftuialertcontrolleruialertaction

How do I pass more parameters to a UIAlertAction's handler?


Is there any way to pass the array "listINeed" to the handler function "handleConfirmPressed"? I was able to do this by adding it as a class variable but that seemed very hacky and now I want to do this for multiple variables so I need a better solution.

func someFunc(){
   //some stuff...
   let listINeed = [someObject]

   let alert = UIAlertController(title: "Are you sure?", message: alertMessage, preferredStyle: UIAlertControllerStyle.Alert)
   alert.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: nil))
   alert.addAction(UIAlertAction(title: "Confirm", style: .Destructive, handler: handleConfirmPressed))
   presentViewController(alert, animated: true, completion: nil)
}

func handleConfirmPressed(action: UIAlertAction){
  //need listINeed here
}

Solution

  • The easiest way is to just pass a closure to the UIAlertAction constructor:

    func someFunc(){
        //some stuff...
        let listINeed = [ "myString" ]
    
        let alert = UIAlertController(title: "Are you sure?", message: "message", preferredStyle: UIAlertControllerStyle.Alert)
        alert.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: nil))
        alert.addAction(UIAlertAction(title: "Confirm", style: .Destructive, handler:{ action in
            // whatever else you need to do here
            print(listINeed)
        }))
        presentViewController(alert, animated: true, completion: nil)
    }
    

    If you really want to isolate the functional part of the routine, you can always just put:

    handleConfirmPressedAction(action:action, needed:listINeed)
    

    into the callback block

    A slightly more obscure syntax, that would retain the feel of a function both in passing it to the completion routine and in the callback function itself would be to define handleConfirmPressed as a curried function:

    func handleConfirmPressed(listINeed:[String])(alertAction:UIAlertAction) -> (){
        print("listINeed: \(listINeed)")
    }
    

    and then you can addAction using:

    alert.addAction(UIAlertAction(title: "Confirm", style: .Destructive, handler: handleConfirmPressed(listINeed)))
    

    Note that the curried function is shorthand for:

    func handleConfirmPressed(listINeed:[String]) -> (alertAction:UIAlertAction) -> () {
        return { alertAction in
            print("listINeed: \(listINeed)")
        }
    }