Reputation: 99
Throughout my program, I call UIAlertControllers multiple times. To make things easier to read, I was able to successfully factor out AlertController if it only has an "OK" action with nil as the handler.
I am struggling to do the same thing if I want to pass a function that I want to link as UIAlertAction. func showOKCancelAlertController does not compile
showOKAlertController(title: "Network Error", message: "Unable to download photos") //This is an example of how I call Alert Controller throughout my code.
extension UIViewController {
func showOKAlertController(title: String, message: String){
let myAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
myAlertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(myAlertController, animated: true)
}
func showOKCancelAlertController(title: String, message: String, okFunction: UIAlertAction ){
let myAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
myAlertController.addAction(UIAlertAction(title: "OK", style: .default, handler: okFunction))
myAlertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
present(myAlertController, animated: true)
}
}
Upvotes: 1
Views: 101
Reputation: 600
Improve your code to my way
This is flexible to deal the completion handler
extension UIViewController {
func showOKAlertController(title: String, message: String? = nil, okCompletion: @escaping (() -> ()) = {}, presentCompletion: @escaping (() -> ()) = {}) {
let myAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default) { (action: UIAlertAction) in
okCompletion()
}
myAlertController.addAction(okAction)
DispatchQueue.main.async {
self.present(alertController, animated: true) {
presentCompletion()
}
}
}
func showOKCancelAlertController(title: String, message: String? = nil, okCompletion: @escaping (() -> ()) = {}, cancelCompletion: @escaping (() -> ()) = {}, presentCompletion: @escaping (() -> ()) = {}) {
let myAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default) { (action: UIAlertAction) in
okCompletion()
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (cancel: UIAlertAction) in
cancelCompletion()
}
myAlertController.addAction(okAction)
myAlertController.addAction(cancelAction)
DispatchQueue.main.async {
self.present(alertController, animated: true) {
presentCompletion()
}
}
}
}
showOKAlertController(title: "message")
or
showOKAlertController(title: "message", message: "message")
or
showOKCancelAlertController(title: "message", message: nil, okCompletion: {
// ok completion handling
}) {
// present completion handling
}
or you can refer above useful from my gist
Upvotes: 1
Reputation: 31695
Clearly, the error that you are facing is:
Cannot convert value of type 'UIAlertAction' to expected argument type '((UIAlertAction) -> Void)?'
that's because okFunction
parameter of type UIAlertAction
, this is the incorrect part. You should let okFunction
to be of type ((UIAlertAction) -> Void)?
instead:
func showOKCancelAlertController(title: String, message: String, okFunction: ((UIAlertAction) -> Void)?) {
let myAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
myAlertController.addAction(UIAlertAction(title: "OK", style: .default, handler: okFunction))
myAlertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
present(myAlertController, animated: true)
}
and that's because the UIAlertAction
init signature is:
init(title: String?, style: UIAlertAction.Style, handler: ((UIAlertAction) -> Void)? = nil)
,
the handler
parameter expects ((UIAlertAction) -> Void)?
.
Therefore, you call it as:
showOKCancelAlertController(title: "title", message: "message") { _ in
print("here is what to do when tapping the OK button")
}
Also, in case there is no action for the OK button, what you could is to give a default nil
value for okFunction
parameter:
func showOKCancelAlertController(title: String, message: String, okFunction: ((UIAlertAction) -> Void)? = nil)
and calling it as:
showOKCancelAlertController(title: "title", message: "message")
Actually, this leads to a pretty cool thing to your case which is: at this point you don't even need to implement two different methods, you could just implement one method and pass the okFunction
parameter for it only if it's needed! Example:
func showAlertController(title: String, message: String, okFunction: ((UIAlertAction) -> Void)? = nil) {
let myAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
myAlertController.addAction(UIAlertAction(title: "OK", style: .default, handler: okFunction))
if let okFun = okFunction {
myAlertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: okFun))
}
present(myAlertController, animated: true)
}
If you want to show it with one button:
showAlertController(title: "title", message: "message")
and for two buttons:
showAlertController(title: "title", message: "message") { _ in
// ...
}
Upvotes: 1
Reputation: 100549
Could be
extension UIViewController {
func showOKAlertController(title: String, message: String,ok:@escaping(() -> ())) {
let myAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
myAlertController.addAction(UIAlertAction(title: "ok", style: .default, handler: { (al) in
ok()
}))
myAlertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
present(myAlertController, animated: true)
}
}
showOKAlertController(title: "This is title", message: "this is message") {
print("ok")
}
Upvotes: 1
Reputation: 1435
The handler expected type is ((UIAlertAction) -> Swift.Void)?
not UIAlertAction
Update your code to
func showOKCancelAlertController(title: String, message: String, okFunction: ((UIAlertAction) -> Swift.Void)? ){
let myAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
myAlertController.addAction(UIAlertAction(title: "OK", style: .default, handler: okFunction))
myAlertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
present(myAlertController, animated: true)
}
Upvotes: 1