The easiest way to learn about this code it to get a working example built.

Open XCode and create a new Single View Application with Use Storyboards and Use Automatic Reference Counting ticked.

There are a few way of using SimpleIOSViewStackController but the most straight forward way is to create a sub class of it and set this as the rootViewController in the AppDelegate.

Create a class that is based on SimpleIOSViewStackController and call it RootNavigationController.

RootNavigationController.h

#import <UIKit/UIKit.h>
#import "SimpleIOSViewStackController.h"

@interface RootNavigationController : SimpleIOSViewStackController

@end

There is a good chance this class was created with an initWithNibName initialiser. Delete this and create a simpler init function which will be added to as this tutorial progresses.

RootNavigationController.m

@interface RootNavigationController()


@end
@implementation RootNavigationController

- (id)init{
   
    self = [super init];
   
    if (self) {
        // stuff will be added here
    }

    return self;
}
 

Initialise this class on the AppDelegate and set it up at the top of the view hierarchy of your app.

AppDelegate.m

#import "AppDelegate.h"
#import "RootNavigationController.h"

@implementation AppDelegate

- (BOOL)application : (UIApplication *) application
        didFinishLaunchingWithOptions : (NSDictionary *) launchOptions{

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
   
    self.rootNavigationController = [[RootNavigationController alloc] init];
    self.window.rootViewController = self.rootNavigationController;
    [self.window makeKeyAndVisible];
   
    return YES;
}
 

You should be able to run your app at this stage. If all is well you will see a NavigationBar at the top of the screen with a black space underneath as there have been no UIViewControllers added as children yet.

Adding UIViewControllers happens in the init method of RootNavigationController.h using a SimpleIOSViewStackVO. You can add UIVIewControllers from storyboards, Nib files or by their class reference.

Storyboards

If you do not have one already add a storyboard to your project and add a UIViewController to it. Next create a class based on UIViewController and call it StoryboardViewController. Return to the storyboard and with the UIViewController selected reveal the Identity Inspector from the left hand interface. Change the Class under the Custom Class heading to StoryboardViewController and also give the ViewController a Storyboard ID of StoryboardViewController. Naming these two things in Identity Inspector the same thing is good practice. Again if you run your application the StoryboardViewController does not appear.

There are two steps needed in order for SimpleIOSViewStackController to display it.
  1. Register it.
  2. Notify SimpleIOSViewStackController
All the registration happens in one place, the init method of RootNavigationController.

RootNavigationController.m

#import "SimpleIOSViewStackNotificationVO.h"
#import "StoryboardViewController.h"

- (id) init{
   
    self = [super init];
   
    if (self) {
       
        // storyboard based UIViewController
        self.storyboardName = @"Storyboard";  // If you only have one storyboard. <- Do once.
       
        SimpleIOSViewStackVO *storyboardViewStackVO = [[SimpleIOSViewStackVO alloc] init];
        storyboardViewStackVO.viewControllerClass = [StoryboardViewController class];

        // If you want to specify a specific storyboard. <- Do every time.
        // storyboardViewStackVO.storyboardName = @"SecondStoryboard";

        storyboardViewStackVO.storyboardID = @"StoryboardViewController";
        storyboardViewStackVO.notificationString = @"ShowStoryboardViewController";
       
        [self registerViewStackVO:storyboardViewStackVO];
       
    }
   
    return self;
}
 

The next step is to notify SimpleIOSViewStackController to display it.


- (void)viewDidLoad{
   
    [super viewDidLoad];
   
    [[NSNotificationCenter defaultCenter] postNotificationName: @"ShowStoryboardViewController" object:nil];

}
 

Finally add a log in to the dealloc method of StoryboardViewController this step is for demonstration purposes and is not necessary to get StoryboardViewController to work.

StoryboardViewController.m


-(void)dealloc{
   
    NSLog(@"%s" , __PRETTY_FUNCTION__ );
   
}
 

If you run your app you will finally see a white screen where there used to be a black one. Happy days.

Nibs

Add a UIButton to StoryboardViewController's view, give it a title of "Show Screen Two" and establish a method of responding to it being tapped. If like me you have added it using the storyboard and created an Action for Touch Up Inside called "screenTwoButtonTapped" in StoryboardViewController you will now have the following method.

StoryboardViewController.m


- (IBAction)screenTwoButtonTapped:(id)sender {
   
}
 

Create a new UIViewController called NibViewController and check the With XIB for user interface check box.

As before add a log in to the dealloc method of NibViewController. This step is for demonstration purposes and is not necessary to get StoryboardViewController to work.

NibViewController.m


-(void)dealloc{
   
    NSLog(@"%s" , __PRETTY_FUNCTION__ );
   
}
 

The final two steps are the same as before, register and notify. Add to RootNavigationController, don't delete anything that is there, I have left some of it out from the code below ... to make it clearer.

RootNavigationController.m


#import "NibViewController.h"

- (id) init{
   
    self = [super init];
   
    if (self) {
       
       ...
       
        SimpleIOSViewStackVO *nibViewStackVO = [[SimpleIOSViewStackVO alloc] init];
        nibViewStackVO.viewControllerClass = [NibViewController class];
        nibViewStackVO.notificationString = @"ShowNibViewController";

        [self registerViewStackVO:nibViewStackVO];
       
    }
   
    return self;
}
 

The notification happens when the button we just made is tapped.


- (IBAction)screenTwoButtonTapped:(id)sender {
   
        [[NSNotificationCenter defaultCenter] postNotificationName: @"ShowNibViewController" object:nil];
   
}
 

Run the app and tap the button. Viola! A transition from StoryboardViewController to NibViewController.

You have probably noticed two things. First the back button on the Navigation Bar disappears as soon as the transition has ended and in XCode's Debug Area you should see a log message that contains the following :


[StoryboardViewController dealloc]
 

These two things are connected and I will explain a little more after showing you how to implement the final method for adding UIViewController's to the RootNavigationController.

Class Reference

Create a new UIButton on the Nib file for NibViewController and in the same way listen out for it being tapped. If you use an Action called "screenThreeButtonTapped" you will now have the following :

NibViewController.m


- (IBAction)screenThreeButtonTapped:(id)sender {
   
   
}
 

Create a new UIViewController by using the new File -> New -> Project -> Objective-C class menu, call it ClassViewController and make sure the With XIB for user interface is not checked.

Add a dealloc method with the same log code.

ClassViewController.m


-(void)dealloc{
   
    NSLog(@"%s" , __PRETTY_FUNCTION__ );
   
}
 

Register the UIViewController in a very similar way.

RootNavigationController.m


#import "ClassViewController.h"

- (id) init{
   
    self = [super init];
   
    if (self) {
       
       ...
       
        SimpleIOSViewStackVO *classViewStackVO = [[SimpleIOSViewStackVO alloc] init];
        classViewStackVO.viewControllerClass = [ClassViewController class];
        classViewStackVO.notificationString = @"ShowClassViewController";

        [self registerViewStackVO:classViewStackVO];

    }
   
    return self;
}
 

Almost identical, apart from the NSNotification name, code is added to the Action.

NibViewController.m


- (IBAction)screenThreeButtonTapped:(id)sender {

    [[NSNotificationCenter defaultCenter] postNotificationName: @"ShowClassViewController" object:nil];
   
}
 

Run the app and you should be able to navigate from the first UIViewController to the last one, notice that there are two dealloc logs now. It may appear that there is something wrong with the third view as it is black however this is because nothing has been done to customise the view. Change the viewDidLoad method so that is looks like the code below and you should see an orange screen once you get to that UIViewController.

ClassViewController.m


- (void)viewDidLoad{

    [super viewDidLoad];

    self.view.backgroundColor = [UIColor orangeColor];

}
 

If you want to be able to easily return to the first screen add a button to do that.

ClassViewController.m


@interface ClassViewController ()

    @property(nonatomic, strong) UIButton *homeButton;

@end
 


- (void)viewDidLoad {
   
    [super viewDidLoad];
       
    self.view.backgroundColor = [UIColor orangeColor];
   
    self.homeButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    self.homeButton.frame = CGRectMake((self.view.frame.size.width / 2) - 40 , 50, 80, 50);
    [self.homeButton setTitle:@"Home" forState:UIControlStateNormal];
    [self.homeButton addTarget:self
                                    action:@selector(homeButtonTapped:)
                     forControlEvents:UIControlEventTouchUpInside];
   
    [self.view addSubview: self.homeButton];
   
}
 


-(void)homeButtonTapped:(id)sender{
   
    [[NSNotificationCenter defaultCenter] postNotificationName: @"ShowStoryboardViewController" object: nil];
   
}
 

You should be able to navigate in a loop now from the first screen to the last and back to the first. Each time you navigate to a new one you should see a deallocation log message.