I'm tired of declaring entire classes as having the ability to handle UIAlertView
clicks by making them extend UIAlertViewDelegate
. It starts to feel messy and wrong when I have multiple possible UIAlertView
s, and have to distinguish which was clicked in the handler.
What I really want is to create a single object that implements the UIAlertViewDelegate
protocol, and give this one-off object to my UIAlertView
when showing it.
I want something like this:
let confirmDelegate = UIAlertViewDelegate() {
func alertView(alertView: UIAlertView!, clickedButtonAtIndex buttonIndex: Int) {
// Handle the click for my alertView
}
}
And then use it when showing the alert:
let alertView = UIAlertView(title: "Confirm", message: "Are you sure?", delegate: confirmDelegate, cancelButtonTitle: "No", otherButtonTitles: "Yes")
alertView.show()
Is this possible without declaring a new class?
I understand I could do something like this:
class ConfirmDelegate: UIAlertViewDelegate {
func alertView(alertView: UIAlertView!, clickedButtonAtIndex buttonIndex: Int) {
// ...
}
}
And then instantiate a ConfirmDelegate()
, but I'm just wondering if this is possible as one-liner class declaration and instantiation.
As @ChrisWagner states in his comment, you shouldn't need to do any of this in iOS8, at least for UIAlertView
since there is a new UIAlertViewController
that uses closures without any delegates. But from an academic point of view, this pattern is still interesting.
I wouldn't use anonymous class at all. I would just create a class that can be assigned as the delegate and accept closures to execute when something happens.
You could even upgrade this to accept a closure for each kind of action: onDismiss
, onCancel
, etc. Or you could even make this class spawn the alert view, setting itself as the delegate.
import UIKit
class AlertViewHandler: NSObject, UIAlertViewDelegate {
typealias ButtonCallback = (buttonIndex: Int)->()
var onClick: ButtonCallback?
init(onClick: ButtonCallback?) {
super.init()
self.onClick = onClick
}
func alertView(alertView: UIAlertView!, clickedButtonAtIndex buttonIndex: Int) {
onClick?(buttonIndex: buttonIndex)
}
}
class ViewController: UIViewController {
// apparently, UIAlertView does NOT retain it's delegate.
// So we have to keep it around with this instance var
// It'll be nice when all of UIKit is properly Swift-ified :(
var alertHandler: AlertViewHandler?
func doSoemthing() {
alertHandler = AlertViewHandler({ (clickedIndex: Int) in
println("clicked button \(clickedIndex)")
})
let alertView = UIAlertView(
title: "Test",
message: "OK",
delegate: alertHandler!,
cancelButtonTitle: "Cancel"
)
}
}
Passing around closures should alleviate the need for anonymous classes. At least for the most common cases.