Search code examples
objective-cxcodeuisplitviewcontrolleruistoryboarduistoryboardsegue

SplitViewController with a Login View Controller as the root


So I've been researching on how to make a login view controller as the initial view controller instead of the splitview.

Some of the answers I've seen would recommend a modal view to be loaded? I'm not sure how that is set up.

eg.

How to add a login view before a UISplitViewController iPad

and

How to implement SplitViewController on second level.?

So do I add those on the loginviewcontroller class? Or where?

Any advice is welcome.

Thanks!!


Solution

  • I've done this by creating two storyboards: one with the (full-screen) login and one with the split-view.

    To switch between them, I've added a custom protocol:

    #import <Foundation/Foundation.h>
    
    @protocol RootViewControllerDelegate <NSObject>
    
    -(void)switchToStoryboard: (UIStoryboard *) storyboad animationDirectionOrNil: (NSString *)direction;
    
    @end
    

    The AppDelegate then implements this protocol:

    -(void)switchToStoryboard:(id)storyboad animationDirectionOrNil:(NSString *)direction {
        UIViewController *newRoot=[storyboad instantiateInitialViewController];
        if ([newRoot respondsToSelector:@selector(setRootViewControllerDelegate:)]) {
            [newRoot setRootViewControllerDelegate:self];
        }
        self.window.rootViewController=newRoot;
    
        if(direction){
            CATransition* transition=[CATransition animation];
            transition.type=kCATransitionPush;
            transition.subtype=direction;
            [self.window.layer addAnimation:transition forKey:@"push_transition"];
        }
    }
    

    As you can see, it tries to set itself as the delegate again, so the other view-controller can switch back or to another storyboard. In order for this to work, you would have to subclass UISplitView:

    Header

    #import <UIKit/UIKit.h>
    #import "RootViewControllerDelegate.h"
    
    @interface MySplitViewController : UISplitViewController
    @property (nonatomic, weak) id <RootViewControllerDelegate> rootViewControllerDelegate;
    
    @end
    

    iMplementation

    #import "MySplitViewController.h"
    
    @implementation MySplitViewController
    @synthesize rootViewControllerDelegate;
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        for (UIViewController *viewController in self.viewControllers) {
            if ([viewController respondsToSelector:@selector(setRootViewControllerDelegate:)]) {
                [viewController setRootViewControllerDelegate:self.rootViewControllerDelegate];
            }
        }
    }
    
    @end
    

    This simple implementation looks for child-view-controllers that accept a root-view-controller-delegate and hands it down. So when you want to add a "Show Login"-button to a certain (master- or detail-)view, just create your own UIViewController-subclass, add a @property id<RootViewControllerDelegate> rootViewControllerDelegate and associate an action like this with the button:

    - (IBAction)loginButtonClicked:(id)sender {
        UIStoryboard *mainSB=[UIStoryboard storyboardWithName:@"LoginStoryboard" bundle:nil];
        NSString *animationDirection=kCATransitionFromTop;
        UIDeviceOrientation currentOrientation=[[UIDevice currentDevice] orientation];
        if (currentOrientation==UIDeviceOrientationLandscapeLeft) {
            animationDirection=kCATransitionFromBottom;
        }
        [self.rootViewControllerDelegate switchToStoryboard:mainSB animationDirectionOrNil:animationDirection];
    }
    

    Feel free to adjust everything to your needs.