Presentations uses ReactiveObjC to make presenting content reactive on iOS. With Presentations you can use commands to present new content. Presentations is designed to intregrate cleanly into the MVVM pattern in a way where your view presentations can be unit tested without instantiating any UIViewController
s.
First we need to define a presenter protocol. This is what the presenting navigation controller will conform to:
@protocol RootNavigationModelPresenter
- (id<AUTPresentation>)presentChild:(ChildViewModel *)viewModel;
@end
Next, we need to add a presenter property to our navigation view model and define a present command.
@interface RootNavigationModel : NSObject
@property (nonatomic, weak) id<RootNavigationModelPresenter> presenter;
@property (readonly, nonatomic) RACCommand<id, ChildViewModel *> *presentChild;
@end
In our implementation for our navigation view model we need to initialize the present command:
_presentChild = [RACCommand aut_presentCommandWithExecutionBlock:^ AUTPresentCommandExecutionContext * _Nullable (id _) {
@strongify(self);
id<RootNavigationModelPresenter> presenter = self.presenter;
if (self == nil || presenter == nil) return nil;
ChildViewModel *child = [[ChildViewModel alloc] init];
id<AUTPresentation> presentation = [presenter presentChild:child];
return [AUTPresentCommandExecutionContext contextWithPresentation:presentation ofViewModel:child animated:@NO];
}];
Finally, we need to set our navigation controller as the presenter and conform to our newly created protocol:
@implementation RootNavigationController
- (instancetype)initWithNavigationModel:(RootViewModel *)navigationModel {
RootViewController *rootViewController = [[RootViewController alloc] init];
self = [super initWithRootViewController:rootViewController];
_navigationModel = navigationModel;
_navigationModel.presenter = self;
return self;
}
- (id<AUTPresentation>)presentChild:(ChildViewModel *)viewModel {
ChildViewModel *viewController = [[ChildViewModel alloc] initWithViewModel:viewModel];
return [self aut_presentationForViewController:viewController];
}
Now we can simply execute the presentation command it will present the child view model
RootNavigationModel *rootNavigationModel = [[RootNavigationModel alloc] init];
RootNavigationController *rootNavigationController = [[RootNavigationController alloc] initWithNavigationModel:rootNavigationModel];
[rootNavigationModel.presentChild execute:nil];
While the presentation is in progress the command will be disabled, which is great when you're hooking up these commands to buttons that you don't want to be executed while a presenantation is in progress. ReactiveObjC's UIKit bindings handle this for us:
button.rac_command = rootNavigationModel.presentChild;
You can use Presentations for more than just pushing view controllers, you could write your own presentations of your protocol methods to do any of the following:
- Present a modal view controller
- Change tabs on a
UITabBarController
- Swap a view controller using view controller containment
- And more!
Dig through the Example scheme in the framework project for more examples.
For deeplinking support check out Routing (used in the Example).
Presentations supports Carthage.
To build the project locally, first run:
$ make bootstrap
Then open the project.
Fork the repository and and open a pull request to the master branch.
Please report any issues found on Github in the issues section.
We use SemVer for versioning. For the versions available, see the tags on this repository.