Uisplitviewcontroller on iPad with Storyboards

UISplitViewController on iPad with Storyboards?

A good starting point for segues are Lectures 6 and 7 of Stanford's CS193p Fall 2011 class.

http://itunes.apple.com/us/itunes-u/ipad-iphone-application-development/id473757255

The instructor, Paul Hegarty, covers everything. However, he runs out of time before the end of class to answer this question. He does include the source with the final solution in the file: Psychologist with Dr Pill.zip.

http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2011-fall

Basically, all that needs to be done for this question is to Ctrl-drag from each UITableCell to the respective game detail view controllers then select the Replace segue. There is one more step because the view controller will shrink because by default Xcode thinks that you want to replace the master controller. For each of the segues, select the connection line and in the Attributes inspector then change the Destination from "Master Split" to "Detail Split". At this point, you can test with the popover, without writing any code.

Master Split Destination

Detail Split Destination

Solution

UISplitViewController on universal app with Storyboard

You don't need two storyboards to do this.You can use them both in a single storyboard.For iphone ,we normally use a class SWRevealViewController(if you are new to iOS coding ..:)) for side menu and splitviewcontroller for ipad.We can also use SWRevealViewController for ipad as well.It depends on your requirement.

For universal apps,create viewcontrollers using size Classes(usually we use any height any width for universal apps ).

change these size classes and create different viewcontrollers for ipad and iphones as required.In most cases any height any width will do the job.

After creating the viewcontrollers,in the appdelegate ,using the instantiateViewcontrollerWithIdentifier method, load the required viewcontroller.

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// The device is an iPad running ios 3.2 or later.

}
else {
// The device is an iPhone or iPod touch.
}

For ipad load the splitviewcontroller. and swrevealviewcontroller for iPhone.

This is the core basics.If you need any more information,let me know.

EDIT

Have you seen an arrowmark ath the initial VC(viewcontroller) in the storyboard?This vc is loaded first after the launch screen.In my app,I have a home screen which is common to both iphone and ipad(using size classes as mentioned above).So I can set this vc as the initial VC.In this case I don't have to do anything in the appdelegate.But if I have a different home screen for ipad,then I can make a condition check in the appdelegate didFinishLaunchingWithOptions

You can load the First screen like this.You should follow through splitVC tutorilal and swrevealcontroller tutorial to set the side menu.You should load the SWrevealVC or splitViewcontroller only if the first screen contains the side menu.

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UISplitViewController *split = [storyboard instantiateViewControllerWithIdentifier:@"SplitViewController"];
[AppDelegate setRootController:split storyboard:storyboard actiontype:0];
}
else if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *split = [storyboard instantiateViewControllerWithIdentifier:@"SWrevealVC"];
[AppDelegate setRootController:split storyboard:storyboard actiontype:-1];
}
return YES;
}

+(void)setRootController:(UIViewController*)controller
storyboard:(UIStoryboard*)storyboard actiontype:(int) actiontype;
{
if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad && actiontype == 0)
{
UISplitViewController *splitViewController = (UISplitViewController *)controller;
//splitViewController.presentsWithGesture = false;

UINavigationController *masterNavigationController = [splitViewController.viewControllers objectAtIndex:0];
SideMenuViewController *controller = (SideMenuViewController *)masterNavigationController.topViewController;
controller.splitViewController = splitViewController;
splitViewController.delegate = (id)controller;
}

AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];

[UIView
transitionWithView:appDelegate.window
duration:0.5
options:UIViewAnimationOptionAllowAnimatedContent
animations:^(void) {
BOOL oldState = [UIView areAnimationsEnabled];

[UIView setAnimationsEnabled:NO];

appDelegate.window.rootViewController = controller;

[UIView setAnimationsEnabled:oldState];
}
completion:nil];
}

The code may look lengthy,but take it simple.You can only understand the logic if u do things.

How to let UISplitViewController on Storyboard show master view first?

In order to enable the master view to collapse on iPhone by default, override some delegate methods:

class SplitViewController : UISplitViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
}

extension SplitViewController : UISplitViewControllerDelegate {

// The default for this is .secondary!!
@available(iOS 14.0, *)
public func splitViewController(_ svc: UISplitViewController,
topColumnForCollapsingToProposedTopColumn
proposedTopColumn: UISplitViewController.Column) -> UISplitViewController.Column {
return .primary
}

// default is false!
public func splitViewController(_ splitViewController: UISplitViewController,
collapseSecondary secondaryViewController:UIViewController,
onto primaryViewController:UIViewController) -> Bool {
return true
}
}

Previously you'd use preferredDisplayMode = .primaryOverlay, but this is now deprecated. The code works for iOS 14 and is backwards compatible for earlier iOS versions also.

iOS - UISplitViewController with storyboard - multiple master views and multiple detail views

If the split view controller delegate was the detail view controller that had been replaced, this is the cause of the crash. The replaced detail view controller is being dealloc'd and so the split view controller delegate is no longer a reference to a valid object.

You can update the delegate in prepareForSegue:sender:. For example:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:@"MySegue"]) {
UIViewController *destinationViewController = [segue destinationViewController];
if ([destinationViewController conformsToProtocol:@protocol(UISplitViewControllerDelegate)]) {
self.splitViewController.delegate = destinationViewController;
}
else {
self.splitViewController.delegate = nil;
}
}
}

Which view controllers you use for delegates is dependent on your view controller hierarchy. In the simplest case, any view controllers that are assigned to splitVC detail will probably need to be delegates. You may want to base them all on a common super class that handles the shared split view controller delegate logic.

UISplitView using Storyboard in Universal iOS app

Have a look at the documentation for UISplitViewControllerDelegate

- (BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation

has been deprecated in iOS8, you have to set the preferredDisplayMode instead:

controller.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;

As for the iPhone app displaying the detail view controller instead of the master, implement the UISplitViewControllerDelegate method:

- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {
return YES;
}

iOS Storyboard UISplitViewController Seque to Full Screen

Instead of using a UISplitViewController, create your own Container View Controller so that you can remove the master view when needed. Check the documentation for UIViewController under the section titled "Implementing a Container View Controller".

Another possibility is to use one of the UISplitViewController replacements which allow you to hide the master view even when you are in landscape mode.

MGSplitViewController is one that a lot of people use: Github link

UISplitViewController Hide/Unhide MasterView In Storyboard

I do it like this in the master view controller (TableController):

#import "TableController.h"
#import "ViewController.h"

@interface TableController ()

@property (strong, nonatomic) NSArray * theData;
@property (strong, nonatomic) UIViewController * detailVC;

@end

@implementation TableController

-(void)awakeFromNib {
self.splitViewController.delegate = self;
self.detailVC = self.splitViewController.viewControllers[1];
}

-(void)splitViewController:(UISplitViewController *)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
NSMutableArray *itemArray = [self.detailVC.toolBar.items mutableCopy];
[itemArray removeObject:barButtonItem];
[self.detailVC.toolBar setItems:itemArray];
}

-(void)splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)pc {
barButtonItem.title = @"Master";
NSMutableArray *itemArray = [self.detailVC.toolBar.items mutableCopy];
if (! itemArray) {
itemArray = [NSMutableArray arrayWithObject:barButtonItem];
}else{
[itemArray insertObject:barButtonItem atIndex:0];
}
[self.detailVC.toolBar setItems:itemArray];
}

I added a tool bar in IB to the detail controller, and gave it the IBOutlet, toolBar.



Related Topics



Leave a reply



Submit