I have a very small Xcode project with several view controllers. I found myself duplicating the following methods in them:
- (void)postTip:(NSString *)message {
[self postInfoAlertWithTitle:@"Tip" andMessage:message andAction:@"Got it!"];
}
- (void)postInfoAlertWithTitle:(NSString *)title andMessage:(NSString *)message andAction:(NSString *)action {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:action style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
}
Of course, this got me thinking about how I might remove (or at least reduce) the duplicated code.
The obvious answer is to put the desired behaviour in a parent class, and then have my view controllers inherit from that class. However, some of the view controllers are of type UICollectionViewController and some are of type UITableViewController, and I don't know how to preserve their collection and table flavours, respectively, in the event that I have them inherit from a hypothetical MyViewController is-a UIViewController.
So I did a bit of research and took a look at protocols. Initially, this seemed like a good fit, except that you can't provide a default implementation for methods declared in a protocol, which is basically what I would want.
Finally, and with much hesitation and self-loathing, I considered placing the behaviour in my AppDelegate class, with an additional parameter to facilitate presenting the alerts:
- (void)postTip:(NSString *)message toController:(UIViewController *)controller;
- (void)postInfoAlertWithTitle:(NSString *)title andMessage:(NSString *)message andAction:(NSString *)action toController:(UIViewController *)controller;
A call in a given view controller looks like this:
[self.appDelegate postTip:@"Git gud!" toController:self];
Et voila! The behaviour I want, where I want it, and all I have to do it get an instance of the AppDelegate! But...that doesn't sit well with me. It seems...smelly. In addition, there is still some duplication, i.e., declaring and initializing a private appDelegate property, which I have taken care to do rather than calling (AppDelegate *)[[UIApplication sharedApplication] delegate] wherever I need it so that:
- I may specify "weak" and avoid possible retain cycles
- I only take one pointer to the AppDelegate (hurray for premature optimization >.<)
Is it considered acceptable to use AppDelegate as a repository for app-wide behaviour such as utility methods, and if so, am I being unnecessarily paranoid about the implementation re: using a property? (If not, what are my options?)