How should you handle closure arguments for UIAlertAction
Yes, you must always handle the argument. It's part of the signature and can't be ignored. It's also special Swift syntax being able to drop the
handler
parameter since it is the last parameter and it is a closure parameter.Change
anything(action)
toanything
just like in the example you link to.You misunderstand. They are not saying you can drop the style parameter. They are saying you can drop the
UIAlertActionStyle
fromUIAlertActionStyle.Default
meaning you only need to pass.Default
as the argument to the style parameter.You want an example of where the
action
parameter to the handler is useful. There aren't too many uses really. The only properties are the title, style, and whether it's enabled or not. The latter is pointless because if the handler was called you know it was enabled. The only possible use is if the title or style need to be used in the handler and they weren't hard coded into the alert action when it was created. By accessing the title or style properties in the handler, you have easy access to the actual values used when the action was created.
Is there a way to pass a closure to UIAlertAction that will return a String in Swift?
If I understood you correctly you could change your method signature to
showSerialNumberAlertController(completion: @escaping (String) -> Void)
and within this function change the continue action to:
let continueAction = UIAlertAction(title: "Continue", style: .default) { (_) in
let serialNumberField = alertController.textFields![0] as UITextField
let text = serialNumberField.text
completion(text ?? "")
}
Finally you call the method like this:
UIAlertController.showSerialNumberAlertController { serial in
print("Serial number entered: \(serial)")
}
UIAlertAction handler is non escaping?
UIAlertAction handler is escaping
because Optional closures are all implicitly escaping (thanks to @sweeper)
UIAlertAction - Handling Actions
You can add two handlers parameters to your showAlert
method, one for the ok action and another for the cancel action. So your code might look something like this:
class AlertDialog {
class func showAlert(_ title: String, message: String, viewController: UIViewController,
okHandler: (() -> Swift.Void),
cancelHandler: (() -> Swift.Void)) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .default, handler: okHandler)
alertController.addAction(OKAction)
let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: cancelHandler)
alertController.addAction(cancelAction)
viewController.present(alertController, animated: true, completion: nil)
}
}
From your viewController you will call:
AlertDialog.showAlert("Ok", message: "Some Message", viewController: self, okHandler: {
//OK Action
},cancelAction: {
//Cancel Action
})
Writing handler for UIAlertAction
Instead of self in your handler, put (alert: UIAlertAction!). This should make your code look like this
alert.addAction(UIAlertAction(title: "Okay",
style: UIAlertActionStyle.Default,
handler: {(alert: UIAlertAction!) in println("Foo")}))
this is the proper way to define handlers in Swift.
As Brian pointed out below, there are also easier ways to define these handlers. Using his methods is discussed in the book, look at the section titled Closures
Right way to make a UIAlertAction's handler
They are all the same, it's mostly a matter of syntactic style you prefer. Option 3 uses type inference and the trailing closure syntax, which is generally preferred as it's concise and gets rid of the extra set of parentheses as it moves the last argument closure outside of the function call. You could one-up option 3 by removing the parentheses around action
, those aren't needed either.
More on this is explained in the Swift Programming Language book, see the section on Closures.
How to pass multiple handlers in UIAlertAction
It's not totally clear what you're asking, but if you are trying to figure out which button was pressed so that you can execute different methods for each one you can do something like this:
@IBAction func buttonClicked(_ sender: UIButton) {
let alert = UIAlertController(title: "Select Value", message: nil, preferredStyle: .actionSheet)
for list in self.listValue {
alert.addAction(UIAlertAction(title: list.value, style: .default, handler: { (action) in
// How do I call different handlers here?
// I'll need to retrieve alert.title in these handlers
switch action.title {
case "Value A":
print("It's Value A")
case "Value B":
print("It's Value B")
default:
print("We didn't implement anything for this value")
}
}))
}
alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel, handler: nil))
self.present(alert, animated: false, completion: nil)
}
Passing Multiple Parameters to an UIAlertAction in Swift
Replace this line:
let joinAction = UIAlertAction(title: "Join", style: UIAlertActionStyle.default, handler: joinSelected(alert: <#UIAlertAction#>, source: source))
with:
let joinAction = UIAlertAction(title: "Join", style: UIAlertActionStyle.default, handler: { [weak self] _ in
joinSelected(source: source)
})
And update joinSelected
to:
fileprivate func joinSelected(source: String) {
Related Topics
Swift 5 Table View Cell with Uiimage Appears Very Tall and Image Extremely Zoomed
How to Make Swiftui Listmenu with Different Behaviors
Programatic Constraints Not Obeyed
Swift 3 Optional Trouble. Can't Unwrap Url with Passed in String
Error: Binary Operator '<=' Cannot Be Applied to Operands of Type 'Int' and 'Int'
When Calling a Function in Swift, What Does Each Part Mean
Xcode & Swift - Window Without Title Bar But with Close, Minimize and Resize Buttons
Build Input File Cannot Be Found' Swift 4.2, Xcode 10.0
How to Do an If-Else Comparison on Enums with Arguments
How to Hide Status Bar and Navigation Bar When Tap Device
Difference Between Dispatchsourcetimer, Timer and Asyncafter
Xcode 6.3 Code Completion Too Slow
Difference Between Type Method and Type Instance Method, etc
How to Define Static Constant in a Class in Swift
How to Trigger an Action When a Swiftui Toggle() Is Toggled
How to Create Uicollectionviewcell Programmatically