Created
October 22, 2014 16:35
-
-
Save fpillet/1e76066643f42681f0fc to your computer and use it in GitHub Desktop.
Chaining VCs from ViewModels
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- (void)pushViewModel:(BaseViewModel *)nextViewModel | |
{ | |
NSString *from = [self standardNameFromViewModel:_currentViewController.viewModel]; | |
NSString *to = [self standardNameFromViewModel:nextViewModel]; | |
// We are going to try and find a segue to go to the next viewModel. The way segues are named | |
// in our storyboard should be: FromModel::ToModel | |
// 1. try Segue method. For example, a segue going from WelcomeViewController to LoginViewController would be named "Welcome::Login" | |
// 2. If a segue is not found, try to instantiate the view controller and push it directly. We look up the view controller by its stripped model name (i.e. "WelcomeViewModel" -> "Welcome") | |
// 3. If the view controller is not found in the storyboard, try a XIB with the stripped model name. | |
@try | |
{ | |
// Hook into currentViewController's -prepareForSegue method to automatically bind view model to instantiated view controller | |
UIViewController *currentVC = (UIViewController *)_currentViewController; | |
if (currentVC) | |
{ | |
// this Aspect hook will execute ONCE on the target view controller and bind the view model | |
// to the UIViewController that was instantiated from a segue | |
[currentVC aspect_hookSelector:@selector(prepareForSegue:sender:) | |
withOptions:AspectPositionAfter | AspectOptionAutomaticRemoval | |
usingBlock:^(id<AspectInfo> ai, UIStoryboardSegue *segue, id sender) { | |
LOG_MODEL(0, @"prepareForSegue from %@ to %@", segue.sourceViewController, segue.destinationViewController); | |
id viewController = segue.destinationViewController; | |
if ([viewController isKindOfClass:[MainTabBarViewController class]]) | |
[self configureTabBarController:(MainTabBarViewController *) viewController withViewModel:nextViewModel]; | |
else | |
[self configureNextController:(BaseViewController *) viewController withViewModel:nextViewModel]; | |
} error:NULL]; | |
} | |
[currentVC performSegueWithIdentifier:[NSString stringWithFormat:@"%@::%@", from, to] sender:self]; | |
} | |
@catch (NSException *exception) | |
{ | |
// Segue not found, try locating the view controller in the storyboard | |
UIViewController *viewController = [self.mainStoryboard instantiateViewControllerWithIdentifier:to]; | |
if (viewController == nil) | |
viewController = [[UIViewController alloc] initWithNibName:to bundle:nil]; | |
if ([viewController isKindOfClass:[MainTabBarViewController class]]) | |
[self configureTabBarController:(MainTabBarViewController *) viewController withViewModel:nextViewModel]; | |
else | |
[self configureNextController:(id<AppViewController>)viewController withViewModel:nextViewModel]; | |
// Since there is no segue, we will push from current navigation controller | |
[((UIViewController *)_currentViewController).navigationController pushViewController:viewController animated:YES]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This code uses the Aspects library by Peter Steinberger https://github.com/steipete/Aspects to automatically configure storyboard segues in MVVM applications when transitioning from one view controller to the other.
To identify the proper segue, we use the source and destination view controller classes and derive a standard format name for the segue. For example, transitioning from a LoginViewController to a MainViewController would look up a segue named "Login::Main" then automagically configure and run it.