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

1

7

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
}
Singlehearted answered 26/1, 2016 at 2:5 Comment(2)
You could also write a method to return your listNeed object and use that method.Chrysotile
@Chrysotile I don't see how that would be any different from assigning it to a class variableSinglehearted
R
22

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)")
    }
}
Respectability answered 26/1, 2016 at 2:14 Comment(4)
But then how do I change this line: alert.addAction(UIAlertAction(title: "Confirm", style: .Destructive, handler: handleConfirmPressed))?Singlehearted
Just like in the example code I give. If you're unfamiliar with Swift and it's closure/block syntax, dig out the Apple Swift book and go through it.Respectability
Ahhh I see what you mean now. I was hoping I didn't have to use a closure and I could just pass in a method, but this way works excellently. Thanks!Singlehearted
In swfit 4 It should be func handleConfirmPressed(listINeed:[String]) -> (_ alertAction:UIAlertAction) -> () { return { alertAction in print("listINeed: (listINeed)") } }Vanny

© 2022 - 2024 — McMap. All rights reserved.