I try to implement adaptive UI in my app. By making UISplitViewController
as the rootview controller, I can run the iPhone's code in iPad too.
I red Apple's documentation about UISplitViewController
and some samples. All are using storyboards and the sample codes are available in swift only. I can not find a working version of code. So I started the code myself.
See my splitview controller class (BaseSplitViewController
)
BaseSplitViewController.h:
#import <UIKit/UIKit.h>
@interface BaseSplitViewController : UISplitViewController <UISplitViewControllerDelegate>
@end
BaseSplitViewController.m:
#import "BaseSplitViewController.h"
#import "TabBarViewController.h"
@interface BaseSplitViewController ()
@property(nonatomic, strong) TabBarViewController *primaryTabBarVC;
@property(nonatomic, strong) UINavigationController *primaryNavigationController;
@property(nonatomic, strong) UINavigationController *secondaryNavigationController;
@end
@implementation BaseSplitViewController
- (instancetype)init
{
self = [super init];
if (self)
{
[self setViewControllers:@[self.primaryNavigationController, self.secondaryNavigationController]];
self.delegate = self;
self.preferredDisplayMode = UISplitViewControllerDisplayModeAutomatic;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cellTapped:) name:@"cellTapped" object:nil];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self assignPrimaryViewController];
}
- (void)assignPrimaryViewController
{
// Need to assign tab bar controller as primary view controller here
}
- (void)assignSecondaryViewController:(UIViewController *)vc
{
// Need to update the secondary controller each time the primary controller was tapped
}
- (UINavigationController *)primaryNavigationController
{
if (!_primaryNavigationController)
{
_primaryNavigationController = [[UINavigationController alloc] init];
}
return _primaryNavigationController;
}
- (UINavigationController *)secondaryNavigationController
{
if (!_secondaryNavigationController)
{
_secondaryNavigationController = [[UINavigationController alloc] init];
}
return _secondaryNavigationController;
}
- (UITabBarController *)primaryTabBarVC
{
if (!_primaryTabBarVC)
{
_primaryTabBarVC = [[TabBarViewController alloc] init];
}
return _primaryTabBarVC;
}
@end
Some points:
- The above class "
BaseSplitViewController
" is the rootview controller of my app.
That is, self.window.rootViewController = [[BaseSplitViewController alloc] init];
- From Apple's Documentation,
"When designing your split view interface, it is best to install primary and secondary view controllers that do not change. A common technique is to install navigation controllers in both positions and then push and pop new content as needed. Having these types of anchor view controllers makes it easier to focus on your content and let the split view controller apply its default behavior to the overall interface."
So, I created two navigation controllers (primary/secondary) and set them as split view controllers's primary & secondary views. setViewControllers:
can be used for this.
- My primary view here is, tab bar view. So, inside the
assignPrimaryViewController:
method, I should assign myTabBarViewController
as split view controller's primary view.
Here, I found two ways.
1. [self.primaryNavigationController showViewController:self.primaryTabBarVC sender:nil];
2. [self.primaryNavigationController pushViewController:self.primaryTabBarVC animated:YES];
Here, I tried with [self showViewController:self.primaryTabBarVC sender:nil];
but my tab bar view was never shown. From my understanding, here "self"
means the UISplitViewController. Calling showViewController
: here makes the confusion to choose the navigation controller. Because we have two navigation controllers. So we need to clearly tell that navigation controller which needs to hold the primary controller.
- Primary view controller part is over. Now the real problem starts. Consider my primary view controller is the tab bar which have tableview's in it. If I tap on the cell, I need to update the secondary view's content. This is the case in Regular mode. In compact mode, I expect when the user taps on the cell, it should push the detail view (secondary view) with back button.
I expect to put the below code within assignSecondaryViewController: vc:
method
[self.secondaryNavigationController pushViewController:vc animated:NO];
[self.primaryNavigationController showDetailViewController:self.secondaryNavigationController sender:nil];
But it does not works.
Questions:
What should be placed inside
assignPrimaryViewController
&assignSecondaryViewController:
methods to get my expected result?And I really, yes really don't know how to implement UISplitViewController's following delegate methods.
primaryViewControllerForCollapsingSplitViewController:
splitViewController:collapseSecondaryViewController:ontoPrimaryViewController:
primaryViewControllerForExpandingSplitViewController:
splitViewController:separateSecondaryViewControllerFromPrimaryViewController:
Would be really helpful, if someone explains this new UISplitViewController's behavior.
Thanks