Is there is any way to hide the master view in a splitviewcontroller programmatically. In my application the first screen will be of a splitviewcontroller, i don't need any split view for the next screens. How i can achieve this
-
When you say hide the masterview, do you mean creating a blank view on the left side of the SplitViewController, or do you mean having the DetailViewController fill 100% of the screen in landscape mode? – Tilo Mitra Apr 23 '10 at 17:11
-
The second option, to have the DetailViewController filling the 100% for the screen in either mode (landscape or portrait). – i0707 Apr 26 '10 at 06:48
-
any solution yet? I am trying to do the same and i tried presenting modally like: – Imran Raheem Jan 21 '11 at 07:06
9 Answers
in SDK 5.0 they added new method for UISplitViewControllerDelegate that would do this easily for you. Just implement it like next and you would not see the master view:
- (BOOL)splitViewController:(UISplitViewController*)svc
shouldHideViewController:(UIViewController *)vc
inOrientation:(UIInterfaceOrientation)orientation
{
return YES;
}
The only place when you can see it is rotation - the part of master view is visible during animation. I've fixed that in simple way, just loaded empty and black view in master.
PS: not sure whether this is actual for i0707. But hope this could be useful for other people that now have the same issues.

- 342
- 4
- 7
-
2Note that the split view controller calls this for all orientations when its `delegate` property is changed. If you want to toggle the behavior you can force it to reload by setting it to nil and back. You still need to trigger the show/hide by calling the rotation methods. – Frank Schmitt Mar 15 '12 at 00:03
-
@FrankSchmitt, can you please clarify what should be set to nil? Can you add some sample code? – Shmidt Apr 04 '12 at 11:07
-
1Doesn't work for me. I've tried it in the SVC, the NC of the master, the VC of the master and the VC of the detail view. – Chris Apr 13 '12 at 11:58
-
1How to enable it again? In iOS 5.1 this method is only called once at the beginning and then never again. Even not when the orientation changes. – Chris Apr 13 '12 at 13:30
-
1
-
So I store a reference to the splitviewcontroller in splitController and a reference to its delegate in splitController, and then at an appropriate time do [splitController setDelegate:nil]; [splitController setDelegate:splitDelegate]; … but nothing seems to happen. – Kaj_Sotala Nov 25 '13 at 06:47
-
In fact, the delegate doesn't seem to get refreshed even if I change it to an entirely different class. – Kaj_Sotala Nov 25 '13 at 11:14
Same as answer from Jack but a one liner. Past into - (void)setDetailItem:(id)newDetailItem { ... } to dismiss the master.
[[UIApplication sharedApplication] sendAction: self.navigationItem.leftBarButtonItem.action
to: self.navigationItem.leftBarButtonItem.target
from: nil
forEvent: nil];

- 1,141
- 10
- 9
-
I searched around for a solution to this problem for hours and this was exactly what I needed. Thanks! – gplocke Feb 14 '14 at 02:45
-
-
This is a particularly elegant solution I find! In my case, I am lazily instantiating a custom bar button item, and this solution did the trick for me when combining it with simply copying over the action and target from the `barButtonItem` returned by the UISplitViewController delegate methods :-) – Erik van der Neut Apr 16 '15 at 05:25
The BarButtonItem provided by the SplitViewController is the key to programmatically hiding the Master View Controller.
This code is DANGEROUS! but elegant :)
import the objective c message library
#import <objc/message.h>
Next, get a handle to the UIBarButtonItem provided by the SplitViewController
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem
forPopoverController:(UIPopoverController *)popoverController
{
barButtonItem.title = @"Master";
[self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
//Obtain handle to BarButtonItem
[self setMasterButtonItem:barButtonItem];
}
Then when the event is fired which should trigger the auto-dismissal of the master view controller i.e.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
You can do this
objc_msgSend(self.masterButtonItem.target, self.masterButtonItem.action);
-
5This is actually a good solution and should be relatively "safe" compared to some of the other ideas posted. You can even skip the `objc_msgSend()` and call `[[UIApplication sharedApplication] sendAction:masterBarButtonItem.action to:masterBarButtonItem.target from:nil forEvent:nil]`. – jrc Mar 15 '13 at 19:09
Matt Gemmell created an excellent custom splitViewController called "MGSplitViewController". It is very easily implemented, heavily commented, and contains a lot of excellent features not found with a normal splitViewController (hide master view on landscape view, change placement of the split in landscape view, allow user to change size of split fluidly during runtime, etc).
Info and demo: http://mattgemmell.com/2010/08/03/mgsplitviewcontroller-updated/
Straight to the source: https://github.com/mattgemmell/MGSplitViewController/

- 1,915
- 3
- 19
- 23
-
1careful with this when building with Xcode 6 and iOS 8..seems to blow up the framing – whyoz Nov 10 '14 at 19:03
The code above didnt work for me, however, when I tried
CGRect selfFrame = self.splitViewController.view.frame;
it did. So....this works for me.. (this code should be in your detailviewcontroller)
-(void)hideMaster {
UIViewController *masterController = GetAppDelegate().masterController;
CGRect selfFrame = self.splitViewController.view.frame;
CGFloat aWidth = masterController.view.frame.size.width;
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.30f];
if(orientation == UIDeviceOrientationLandscapeLeft)
{
selfFrame.size.height += aWidth;
selfFrame.origin.y -= aWidth;
}
else if(orientation == UIDeviceOrientationLandscapeRight)
{
selfFrame.size.height += aWidth;
}
[self.splitViewController.view setFrame:selfFrame];
[UIView commitAnimations];
}
To allow rotation this was needed:
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation duration:(NSTimeInterval)duration
{
[super willAnimateRotationToInterfaceOrientation:interfaceOrientation duration:duration]; // not sure if needed
//By the time this method is called the bounds of the view have been changed
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
if (UIInterfaceOrientationIsPortrait(interfaceOrientation)) {
if (masterIsHidden) {
[self showMaster];
}
} else {
if (self.editing) {
[self hideMaster];
}
}
[UIView setAnimationDuration:duration];
[UIView commitAnimations];
}
-
This works great for me. I use it in a detail view when entering editMode. I created a showMaster method by saving the master width in an iVar and then just reversing the += and -+ signs in hideMaster. My implementation also use a masterIsHidden iVar to prevent hiding the view when it was already hidden. – T.J. Jun 04 '14 at 16:36
Try this:
splitVC.modalPresentationStyle = UIModalPresentationFullScreen;
[splitVC presentModalViewController:[[splitVC viewControllers] objectAtIndex:1] animated:NO];
Works on 4.2 for me!
Here is another awesome trick that works. video link is here.

- 396
- 5
- 7

- 890
- 8
- 25
-
1It will certainly hide the master view, but I cannot seem to bring it back after calling presentModalViewController. – ericg Mar 24 '11 at 21:40
-
-
-
doesn't work if the VCs in your detail side are under a navigation controller :( – Yoga Oct 18 '13 at 05:13
While it will not have nice transitions (sorry), you could do this by setting the root view to the detail view controller's view, and then swap views with the UISplitView and move the detail view to the UISplitView. (Actually you might be able to animate the view swap (push/flip/etc.) but it is a bad idea to change anything during view change animations, and moving the detail view to inside the UISplitView might qualify.)

- 4,925
- 2
- 29
- 39
Don't know if this is what your are looking for. For example, to hide master view in landscape mode when a button is clicked you can do the following (in the selector method)
UIViewController *master = [splitViewController.viewControllers objectAtIndex:0];
UIViewController *detail = [splitViewController.viewControllers objectAtIndex:1];
[master.view setFrame:CGRectMake(0, 0, 0, 0)];
detail.view.frame = splitViewController.view.bounds; // or use master and detail length
-
Do you see any size change. The code above did work for me. Try manually setting the detail.view.frame size to see the size update. if not I'll post some detail code tomorrow. – surajz Mar 26 '11 at 20:49
This works:
Attach the "hide" method to your button, for example:
UIBarButtonItem *hideButton = [[UIBarButtonItem alloc] initWithTitle:@"hide"
style: UIBarButtonItemStylePlain
target: self
action: @selector(hide:)
];
[self.mainView.navigationItem setLeftBarButtonItem:hideButton];
In this code, the "self.mainView" is the view controller in the navigation controller in the second view of the splitview - just as a reference.
The hide method looks like so.
-(void)hide:(id)sender
{
UIViewController *masterController = [self.viewControllers objectAtIndex:0];
CGRect selfFrame = self.view.frame;
CGFloat aWidth = masterController.view.frame.size.width;
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.30f];
if(orientation == UIDeviceOrientationLandscapeLeft)
{
selfFrame.size.height += aWidth;
selfFrame.origin.y -= aWidth;
}
else if(orientation == UIDeviceOrientationLandscapeRight)
{
selfFrame.size.height += aWidth;
}
[self.view setFrame:selfFrame];
[UIView commitAnimations];
}
This is the starting point, obviously more logic needs to be done to take care of rotation, showing it again, etc...
I hope this helps.
Tested with iOS5 and Xcode 4.3

- 151
- 1
- 8