Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is it acceptable to reduce code duplication by placing the code in AppDelegate?

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?)

like image 969
kuipersn Avatar asked Mar 12 '26 15:03

kuipersn


1 Answers

Definitely use a category by creating .h and .m files

UIViewController+InfoAlert.h

@interface UIViewController (InfoAlert)

- (void)postInfoAlertWithTitle:(NSString *)title andMessage:(NSString *)message andAction:(NSString *)action;

@end

UIViewController+InfoAlert.m

#import "UIViewController+InfoAlert.h"

@implementation UIViewController (InfoAlert)

- (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];
}

@end

then just import your UIViewController+InfoAlert.h where you want to use your new postInfoAlertWithTitle method

like image 87
user6943228 Avatar answered Mar 15 '26 07:03

user6943228



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!