I'm developing an app which is essentially a sequence of many different tests (for simplicity, think about an SAT test or a Mensa test). Each test is implemented in a different View+View Controller.
Initially I wanted to use Storyboards and UINavigationControllers for managing the sequence of the tests and the transitions between them, but now I'm questioning the validity of this approach. A UINavigationController is a stack while my navigation is one-way only (once you've completed a test you can't go back). Is there a better way to implement the app? Can I still leverage Storyboards somehow?
I'd use a custom container view controller. So to your main scene, add a "container view". If your target is iOS6, then when editing your storyboard there is a special "container view" object that you can now drag onto your custom container view controller's scene:
If iOS 5, then (a) you have to create the first child scene manually; (b) give it a unique storyboard id (in my example, InitialChild
, and (c) you manually instantiate that first child controller and add it as a child programmatically. Thus, assuming you have a UIView
called containerView
in your custom container view controller's scene, you can have a method like:
- (void)addInitialChild
{
UIViewController *child = [self.storyboard instantiateViewControllerWithIdentifier:@"InitialChild"];
[self addChildViewController:child];
child.view.frame = self.containerView.bounds;
[self.containerView addSubview:child.view];
[child didMoveToParentViewController:self];
}
When you want to transition to the next scene, subclass your own UIStoryboardSegue
:
In ReplaceSegue.h:
@interface ReplaceSegue : UIStoryboardSegue
@end
In ReplaceSegue.m
@implementation ReplaceSegue
- (void)perform
{
UIViewController *source = self.sourceViewController;
UIViewController *destination = self.destinationViewController;
UIViewController *container = source.parentViewController;
[container addChildViewController:destination];
destination.view.frame = source.view.frame;
[source willMoveToParentViewController:nil];
[container transitionFromViewController:source
toViewController:destination
duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
}
completion:^(BOOL finished) {
[source removeFromParentViewController];
[destination didMoveToParentViewController:container];
}];
}
@end
Then, when doing a segue from the first contained scene to the next, specify a "custom" segue, and use this "ReplaceSegue" as the class (just click on the segue to select it and then look at the "Attributes inspector").
The resulting storyboard might look like (note the "{}
" designation between the various children):
References:
For general discussion of containment, see Implementing a View Container Controller in the UIViewController Class Reference.
For some details about the implementation, see Creating Custom Container View Controllers in the View Controller Programming Guide for iOS.
Then just load the next view controller and replace current view (in some top-level view or in app window) with the new one. Add animations if you want. What's the problem?
You can also use view animation to avoid push viewcontrollers.you can give view animation like pushing a VC