While shipping an app in a timely manner should be our top priority, writing well structured code is critical for maintaining and improving your app in the long run. One way to do this is to decouple UI navigation code from your view controllers via a router, so your view controllers know less about each other.
routable-ios by @clayallsopp is a good library for this.
You set up the router in a centralized location, e.g. in your app delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController:[SomeViewController new]];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = nc;
[self.window makeKeyAndVisible];
[[Routable sharedRouter] map:@"users/:username" toController:[UserViewController class]];
[[Routable sharedRouter] map:@"places/:id" toController:[PlaceViewController class]];
[[Routable sharedRouter] setNavigationController:nc];
}
Instead of writing code like this to display a user:
- (void)openUserWithUsername:(NSString*)aString {
UserViewController* vc = [UserViewController new]
vc.username = aString;
//Or worse, you may need to figure if you have a navigation controller here
[self.navigationController pushViewController:vc animated:YES];
}
You do this, without coupling the current view controller to UserViewController
:
- (void)openUserWithUsername:(NSString*)aString {
NSString* url = [NSString stringWithFormat:@"users/%@", aString];
[[Routable sharedRouter] open:url];
}
UserViewController
needs to implement -initWithRouterParams:
to accept the routing argument(s):
- (id)initWithRouterParams:(NSDictionary*)params {
if ((self = [self initWithNibName:nil bundle:nil])) {
self.username = [params objectForKey:@"username"];
}
return self;
}
There are a few more options listed in the README.
You can install it using CocoaPods.
Your feedback is valuable: Do you want more nuggets like this? Yes or No
.
.