As I was working on a toy iOS project today, I found myself typing in a bunch of boiler plate code to present errors with a UIAlertController
. This resulted in me wondering if there was a way in which I could avoid repeating the same code over and over again.
My first solution to the problem was to create an extension on UIViewController
:
extension UIViewController {
func showError(title: String, message: String? = nil) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
let dismissAction = UIAlertAction(title: "Dismiss", style: .Cancel, handler: nil)
alertController.addAction(dismissAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
}
I wasn’t particularly happy with this though, since this results in every UIViewController
in my app having showError
function. Not every one of them needs it, though. I figured there must be some way in Swift to opt each UIViewController
into having this function one at a time. Here’s the best solution I came up with:
protocol ErrorPresenter {
func showError(title: String, message: String)
}
extension ErrorPresenter where Self: UIViewController {
func showError(title: String, message: String? = nil) {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
let dismissAction = UIAlertAction(title: "Dismiss", style: .Cancel, handler: nil)
alertController.addAction(dismissAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
}
Now, all I have to do to opt a particular UIViewController
into having this function is have it conform to ErrorPresenter
:
class MyViewController: UIViewController, ErrorPresenter {
// stuff
}
The only problem I can think of with this solution is that you cannot have any internal state in this extension since extensions can’t have stored properties. This would prevent me from creating a CoalescedErrorPresenter
, which could for instance keep track of all calls to showError
, and only show a UIAlertController
once every X seconds. If you can think of any solutions to this problem I’d love to know. Hit me up @gopalkri.