I am building an application that is for iOS6+. The application will have a main View Controller at one point in the application.
I would like this main view controller to handle a swipe left and swipe right on screen to then show another view controller.
Is there an easy way to accomplish this in core iOS6+, or should I look for another library etc.
I already use a slide in menu style else where in the application. I also understand and can find a million alternatives to these.
What I am looking for is to have one View Controller (which acts in the 'middle'). Then when they swipe left/right another view controller is shown. They can then swipe back the opposite direction or click a back button to return to the main controller.
EDIT-
Specifically I am looking for the functionality to do the following:
Pre-load the controller that will slide in.
When the swipe occurs (is happening)... the controller to drag/slide in with the touch.
The same drag/swipe to occur either way the controller is swiped (lefT/right).
EDIT 2 -
I am looking for the functionality of dragging the view controller in with the finger. Dependant on which way the drag is occurring, it would be pulling the same view controller in.
I.e the layout would be:
[VC for Drag] [Main controller] [VC for Drag].
If the user swipes from left to right, or right to left the other controller is dragged over the top and they can return to the Main controller using the opposite entry swipe.
My favorite side-drawer controller: https://github.com/mutualmobile/MMDrawerController
MMDrawerController is highly configurable and does all the things you mention:
support for left and right controllers
preloads side controllers
"dragging" open with a gesture
If you're using a storyboard you can use this extension to have storyboard support: https://github.com/TomSwift/MMDrawerController-Storyboard
EDIT:
Another option might be to use a UIPageViewController with a transition style of UIPageViewControllerTransitionStyleScroll: https://developer.apple.com/library/ios/documentation/uikit/reference/UIPageViewControllerClassReferenceClassRef/UIPageViewControllerClassReference.html
This will have the behavior of "pulling" in the side view controllers vs. "uncovering" them.
EDIT 2: example per request
The only real complicating requirement you have is that the same view controller is used for both left and right. That means we have to track where the view controller is being presented so that we can correctly manage our data source. Without this requirement we could just back our data source with an array and derive next/prev from that.
First, the storyboard. The storyboard has three view controllers: 1) the UIPageViewController, which I've subclassed as TSPageViewController. Don't forget to set the page controller transition-style property to 'scroll'. 2) the "center" view controller, and 3) the "side" view controller. For center and side I've set the storyboard ID of each to "center" and "side", respectively. For this sample, both the center and side controllers are plain vanilla UIViewControllers, and I've set their view backgroundColor's to tell them apart.
Second, the page view controller:
.h
#interface TSPageViewController : UIPageViewController
#end
.m
#interface TSPageViewController () <UIPageViewControllerDataSource>
#end
#implementation TSPageViewController
{
UIViewController* _side;
UIViewController* _center;
}
- (void) viewDidLoad
{
[super viewDidLoad];
self.dataSource = self;
_side = [self.storyboard instantiateViewControllerWithIdentifier: #"side"];
_center = [self.storyboard instantiateViewControllerWithIdentifier: #"center"];
[self setViewControllers: #[_center]
direction: UIPageViewControllerNavigationDirectionForward
animated: NO
completion: nil];
}
- (UIViewController*) pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
if ( viewController == _center )
{
_side.title = #"right";
return _side;
}
if ( viewController == _side && [_side.title isEqualToString: #"left"] )
{
return _center;
}
return nil;
}
- (UIViewController*) pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
if ( viewController == _center )
{
_side.title = #"left";
return _side;
}
if ( viewController == _side && [_side.title isEqualToString: #"right"] )
{
return _center;
}
return nil;
}
#end
Again, the only thing here that's special is the tracking of the whether the side controller is currently "left" or "right". This implementation has an issue in that it relies on the behavior of the UIPageViewController to not "page ahead" and cache view controllers (if it did, our logic would get confused). So you might want to consider a more robust mechanism to track which side the view controller is currently on. For that you'd likely have to introduce your own swipe gesture recognizer and use the data from that to drive tracking left/right.
If you can toss your requirement of using the same view controller for left and right, then you can have separate left/right/center controllers, stored in an array, and return next/prev controllers based on what you see in the array. Much easier and more robust!
for iOS6+:
I'd be inclined to use https://github.com/pkluz/PKRevealController and just set both left and right viewControllers to be pointers to a single viewController.
for iOS7+:
I think you should be looking into custom UIViewController transitions.
https://github.com/ColinEberhardt/VCTransitionsLibrary
http://www.teehanlax.com/blog/custom-uiviewcontroller-transitions/
There is a good WWDC 2013 video on this subject entitled "Custom transitions using view controllers", it's session 218.
You can accomplish that with some of the cocoa controls such as:
https://github.com/Inferis/ViewDeck
https://github.com/gotosleep/JASidePanels
EDIT: Proposal number two, use a controller with a scrollView:
// Allocate all the controlelrs you need
MyFirstViewController *first = [[MyFirstViewController alloc] init];
MySecondViewController *second= [[MySecondViewController alloc] init];
MyThirdViewController *third = [[MyThirdViewController alloc] init];
// Adjust the frames of the controllers
first.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
second.view.frame = CGRectMake(0, self.view.frame.size.width, self.view.frame.size.width, self.view.frame.size.height);
third .view.frame = CGRectMake(0, 2 * self.view.frame.size.width, self.view.frame.size.width, self.view.frame.size.height);
// Add controllers as subViews to the scrollView
[self.scrollView addSubview:self.first.view];
[self.scrollView addSubview:self.second.view];
[self.scrollView addSubview:self.third.view];
// Set the scrollView contentSize and paging
self.scrollView.contentSize = CGRectMake(self.view.frame.size.width * 3, self.view.frame.size.height);
self.scrollView.pagingEnabled = YES;
// Scroll to the middle view initally
[self.scrollView scrollRectToVisible:CGRectMake(0, self.view.frame.size.width, self.view.frame.size.width, self.view.frame.size.height) animated:NO];
The code above is written by heart, I have probably named a few things wrongly, and there is more than one way to handle the subviews. The mentioned pageViewController in the comments will work as well.
What you are looking to do sounds a lot like the iPhone version of Apple's UIPageControl Demo;
Sounds like a job for UISwipeGestureRecognizer.
Related
You can see on the gif below that on the first scroll of UITableView cell's content moves a tiny bit. You can barely see it, margins become 1 pixel wider.I've never encountered this before. It seems like there's some layout issue before the first scroll and it resolves itself after the fact. There's no warning in XCode, these custom cells are pretty straightforward, with no layout code overrides.
I don't know where to start, how do I catch this glitch?
UPDATE. I've implemented an obvious workaround for now:
- (void)scrollTableToFixGlitch {
[self.tableView setContentOffset:CGPointMake(0, 1)];
[self.tableView setContentOffset:CGPointMake(0, -1)];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self scrollTableToFixGlitch];
}
Still looking into the problem. I've tried generic UITableViewCells, nothing changed. Seems like it's the problem with View Controller's root view or tableview layout, and not with the table cells.
UPDATE 2.
I ruled out all the animations out of the question, problem lies somewhere in a different region. The glitch is easy to recreate on a much simplified project. My Tab Bar controller is based on MHCustomTabBarController with custom segues and some other additions. Here's what you do to recreate a glitch. Setup a project where your initial VC is embedded in Navigation Controller. The next controller either MHCustomTabBarController or a subclass is pushed to the navigation stack. First visible VC in tab bar is generic Table View Controller. That's it. Glitch appears only if tab bar controller is pushed in navigation stack.
Here's some code that I think matters from tab bar controller:
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (self.childViewControllers.count < 1) {
[self performSegueWithIdentifier:#"viewController1" sender:[self.buttons objectAtIndex:0]];
}
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if (![segue isKindOfClass:[MHTabBarSegue class]]) {
[super prepareForSegue:segue sender:sender];
return;
}
self.oldViewController = self.destinationViewController;
//if view controller isn't already contained in the viewControllers-Dictionary
if (![self.viewControllersByIdentifier objectForKey:segue.identifier]) {
[self.viewControllersByIdentifier setObject:segue.destinationViewController forKey:segue.identifier];
}
[self.buttons setValue:#NO forKeyPath:#"selected"];
[sender setSelected:YES];
self.selectedIndex = [self.buttons indexOfObject:sender];
self.destinationIdentifier = segue.identifier;
self.destinationViewController = [self.viewControllersByIdentifier objectForKey:self.destinationIdentifier];
[[NSNotificationCenter defaultCenter] postNotificationName:MHCustomTabBarControllerViewControllerChangedNotification object:nil];
}
And a custom segue code:
#implementation MHTabBarSegue
- (void) perform {
MHCustomTabBarController *tabBarViewController = (MHCustomTabBarController *)self.sourceViewController;
UIViewController *destinationViewController = (UIViewController *) tabBarViewController.destinationViewController;
//remove old viewController
if (tabBarViewController.oldViewController) {
[tabBarViewController.oldViewController willMoveToParentViewController:nil];
[tabBarViewController.oldViewController.view removeFromSuperview];
[tabBarViewController.oldViewController removeFromParentViewController];
}
destinationViewController.view.frame = tabBarViewController.container.bounds;
[tabBarViewController addChildViewController:destinationViewController];
[tabBarViewController.container addSubview:destinationViewController.view];
[destinationViewController didMoveToParentViewController:tabBarViewController];
}
#end
UPDATE 3
During my research I've found that - viewWillAppear is not called the first time when child controller appears. But it's called in all subsequent times.
Maybe the scrollviews contentSize is wider than your scrollView's frame(width specifically in this case) causing scrolling for both directions.
You can either try to decrease the contentSize width to the scrollView's width and
self.scrollView.alwaysBounceHorizontal = NO;
If this doesn't work, the solution would be to disable horizontal scrolling programatically by the help of the UIScrollView delegate
self.scrollView.delegate = self;
[self.scrollView setShowsHorizontalScrollIndicator:NO];
//for the below UIScrollView delegate function to work do the necessary step in the bottom of my answer.
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView.contentOffset.x > 0)
scrollView.contentOffset = CGPointMake(0, scrollView.contentOffset.y);
}
And in your .h file you should change the interface line to below by adding UIScrollViewDelegate
#interface ViewController : UIViewController <UIScrollViewDelegate>
You most probably know this delegate part very well but for others it might be needed:D
Original answer
Ah, I've finally found the origin of this behaviour. I was almost sure this is happening due to some of the preparation methods are not called properly. As I stated in the update 3 I've found that -viewWillAppear method is not called in TableViewController when my TabBarController is pushed to the navigation stacked. I've found a ton of coverage of this matter on SO, it's a very well known issue apparently.
I've added a simple fix just to check if I'm right in my Custom Segue:
//added this line
[destinationViewController viewWillAppear:YES];
[tabBarViewController.container addSubview:destinationViewController.view];
And it works like a charm, no flickering! Now I have to figure out a more suitable place for this call, since explicit calls to methods like this can break a lot of stuff.
Probably the best place is in -navigationController:willShowViewController:animated: method of UINavigationControllerDelegate.
Anyway, problem solved. Hope it will help someone with the same issue.
UPDATE Actually, I was not completely correct on that. -viewWillAppear is called on my tab bar controller when it's pushed to navigation stack. It's not being translated to TableViewController. So there's no need to access NavigationControllerDelegate. Simple fix to a custom segue is enough.
I am trying to add custom UIViewController on top of everything but not covering full screen (basically popover), like this:
- (void) displayPopoverController: (UIViewController*) content;
{
[self addChildViewController:content];
content.view.frame = [self frameForContentController];
[self.view addSubview:content.view];
[content didMoveToParentViewController:self];
}
Everything works, but unfortunately it is underneath the navigation bar. So I decided to add UIViewController to the navigation controller like this:
- (void) displayPopoverController: (UIViewController*) content;
{
[self.navigationController addChildViewController:content];
content.view.frame = [self frameForContentController];
[self.navigationController.view addSubview:content.view];
[content didMoveToParentViewController:self.navigationController];
}
It worked, but there are 2 problems:
1) viewWillAppear is not called when I add popover (only viewDidLoad is called)
2) If I change orientation, my popover receives notification and adjusts to new orientation, but UIViewController behind it does not. It will only update its view after I remove popover.
Is there any way to fix 1 and 2? Maybe there is better approach(I don't want to use UIPopoverController with custom UIPopoverBackgroundView)?
IMO you should make a custom transition and present UIViewController modally.
You can get help on Custom UIViewController transition here : http://www.doubleencore.com/2013/09/ios-7-custom-transitions/
I am trying to add custom UIViewController on top of everything but not covering full screen
If you can confine yourself to iOS 7, your problems are over. You can use presentViewController: and a custom transition to do exactly what you are trying to do. This, in my view, is the most important new feature of iOS 7: you can present a view controller's view only partially covering the main interface.
See my book; for the particular example code from the book, see https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch06p304customPresentedAnimation2/ch19p620customPresentedAnimation2/ViewController2.m
Plus I've now posted a single project at https://github.com/mattneub/custom-alert-view-iOS7. It shows how to make a view controller presented view that only partially covers the interface, plus it demonstrates that device rotation works correctly for all visible views (i.e. what's in front and what's visible behind).
I have a UINavigationController (NC) containing a UITableViewController (TVC0). When the user taps a row, it loads a UIPageViewController (PVC), which pages back and forth between other UITableViewControllers (TVC1).
TVC0 shows up inside NC (meaning it doesn't hide behind the navigation bar at the top or the tab bar at the bottom). When it pushes PVC, the first TVC1 appears inside the bounds of the nav bar and tab bar. However when I swipe, the TVC1s inside are hidden behind the navigation bar and tab bar. I can pull to reveal the contents, but when I release, it snaps back to behind the bar.
How can I force everything to appear between the two bars? I can't use storyboard (because it's a legacy app) and the embed in... option isn't available.
[Edit]
I added some logging and discovered that my embedded TVC1s frame has an absolute origin of 0, 64, but as soon as I tap, it goes to 0, 0. If I can't figure out a real solution, I can always fake it by adding 64, but I'd much rather figure out what's actually wrong.
[/Edit]
[More Edit]
I was testing another area in the iOS 6 simulator and discovered that this paging works flawlessly in iOS 6. So the issue I'm seeing is iOS 7 specific.
[/More Edit]
Here is my TVC0 viewDidLoad, PVC pageViewController:viewControllerBeforeViewController:, and a helper viewControllerAtIndex::
- (void) viewDidLoad
{
[super viewDidLoad];
NSDictionary* options = [NSDictionary dictionaryWithObject:
[NSNumber numberWithInteger: UIPageViewControllerSpineLocationMin]
forKey:
UIPageViewControllerOptionSpineLocationKey];
self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:
UIPageViewControllerTransitionStyleScroll
navigationOrientation:
UIPageViewControllerNavigationOrientationHorizontal
options: options];
self.pageController.dataSource = self;
self.pageController.view.frame = self.view.frame;
NSArray* viewControllers =
[NSArray arrayWithObject: [self viewControllerAtIndex: self.initialIndex]];
[self.pageController setViewControllers: viewControllers
direction: UIPageViewControllerNavigationDirectionForward
animated: NO
completion: nil];
[self addChildViewController: self.pageController];
[self.view addSubview: self.pageController.view];
[self.pageController didMoveToParentViewController: self];
for (UIGestureRecognizer* recognizer in self.pageController.gestureRecognizers)
{
if ([recognizer isKindOfClass: [UITapGestureRecognizer class]])
{
recognizer.enabled = NO;
}
}
}
// SearchResultsList is TVC1
- (SearchResultsList*) viewControllerAtIndex: (NSUInteger) index
{
if (index >= self.items.count)
{
return nil;
}
SearchResultsList* retVal = [[SearchResultsList alloc]
initWithNibName: #"SearchResultsList" bundle: nil];
MyListItem* myItem = [self.items objectAtIndex: index];
MyMatchesRequest* matches = [[MyMatchesRequest alloc] initWithItemId: myItem.itemId];
[matches execute: ^(MySearchResults* results)
{
retVal.tableData = [NSMutableArray arrayWithArray: results.items];
retVal.view.frame = self.view.frame;
retVal.myItem = myItem;
retVal.index = index;
self.title = myItem.displayText;
[[retVal tableView] reloadData];
}];
return retVal;
}
- (UIViewController*) pageViewController: (UIPageViewController*) pageViewController
viewControllerBeforeViewController: (UIViewController*) viewController
{
SearchResultsList* vc = (SearchResultsList*)viewController;
if (vc.index == 0)
{
[self.navigationController popViewControllerAnimated: YES];
return nil;
}
return [self viewControllerAtIndex: vc.index - 1];
}
I had a very painful learning experience with similar behavior :(
Put this in your view controller's init:
self.automaticallyAdjustsScrollViewInsets = NO;
This is a new UIViewController property that defaults to YES in iOS 7
UIViewController Docs
Because you're presenting view controllers in a container which is less than the full size of the screen you need to set
self.pageViewController.definesPresentationContext = YES;
viewControllerWhichIsApageInPageController.modalPresentationStyle = UIModalPresentationCurrentContext
You code seems a little confused. You say it is your Page View Controller's viewDidLoad, yet it creates a new PVC and adds it as a child view controller to itself as parent. If you are really doing this, you are creating a PVC inside another PVC. I doubt this is what you want.
This code really belongs in TVC0 which invokes the PVC when the user taps a row. This invocation wouldn't be correct in viewDidLoad, but might sit nicely in a didSelectRowAtIndexPath method. Instead of bringing it in as a child controller, we can simply push it onto our navigationController's stack. (I expect you are doing this anyway in your outermost PVC).
But just in case, I would remove these three lines:
[self addChildViewController: self.pageController];
[self.view addSubview: self.pageController.view];
[self.pageController didMoveToParentViewController:self];
and replace them with
[self.navigationController pushViewController:self.pageController
animated:YES];
(this is called from your TVC0 - all of the code you have shown can live in TVC0)
Then to prevent the behaviour you describe, when you create your UINavigationController it should suffice to set the translucent property of it's navigationBar to NO.
update
I have looked at this issue in sufficient detail to see some buggy behaviour as you describe occur in some circumstances, but it's fairly hard to replicate.
The cause of the 'jump-up' behaviour is clear. If you have a translucent navBar, and it's automaticallyAdjustsScrollViewInsets is set to YES, in certain situations this can result in a private subview of the pageViewController (_UIQueuingScrollView) setting it's contentOffset.y to -64 when the pageViewController is first loaded. However as soon as the pageVC gets a chance to update itself (for example by a swipe or other touch gesture) it resets it's internal subviews state, losing that rogue contentOffset. So when you touch the first page, it jumps up. Where it then stays. This may be considered a bug, although it may be the result of misusing the pageViewController.
Just setting automaticallyAdjustsScrollViewInsets to NO doesn't cure your ills, as then your pages are all positioned behind the navBar. What you need to do is adjust the frame of the pageViewController itself.
I could go in to more detail, but at that point it gets hard to apply answers to your specific case as your app design looks a little odd, which is probably contributing to the issue.
if you can set your navigation controllers' navigation bar's translucent property to NO the problem should go away.
as I mentioned earlier, I cannot replicate your issue exactly as you describe, so I think you have not given a full and clear picture of your app design
loading a pageViewController as a child of a tableViewController, and making it's view a subview of the tableView, is a very odd way to go, and is doubtless contributing to your problems.
In viewControllerBeforeViewController the pageViewController child seems to pop it's parentViewController (the tableViewController) - so you would never see it's table contents? Either there is more relevant detail to the app, or you haven't described it accurately.
I recommend you first deal with these issues. Your problem may well then disappear.
I'm currently trying to make a small demo app which is supposed to present 2 views at the same time :
- The first one, BaseViewController, is a classic controller with 2 buttons
- The second one, OverViewController, is launch on top of baseView and contains
a last button, and is supposed to be transparent and sending the touch controls
to the first one
Both viewController have their xib. To make it clear : rootView --> baseView + overView (transparent)
My problem is NOT to send the control events from the 2nd view to the first, but to make the 2nd view transparent and functionnal.
Here's what I've tried so far :
1) ------------ Presenting the two view controllers ------------
From the app rootViewController :
- (IBAction)buttonClicked:(id)sender
{
OverViewController *overVC = [[OverViewController alloc] init];
[overVC presentViewControllerFrom:self];
}
From OverViewController :
- (id)init
{
self = [super init];
if (self)
{
self.base = [[BaseViewController alloc] initWithNibName:#"BaseViewController" bundle:nil];
}
return self;
}
I made a custom method to make overView present the baseView before showing up.
- (void)presentViewControllerFrom:(RootViewController *)sender
{
[sender presentViewController:self.base animated:NO completion:nil];
self.view.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.0];
self.view.opaque = NO;
[self.base presentViewController:self animated:YES completion:nil];
}
At this point, the baseView appears, followed by the overView. The button of overView work correctly. Great ! But then the background of overView doesn't show what's supposed to be behind and stays black. No alpha transparency.
2) ------------ Presenting the baseView and adding overView as a subview ------------
From the app rootViewController (same than the one before) :
- (IBAction)buttonClicked:(id)sender
{
OverViewController *overVC = [[OverViewController alloc] init];
[overVC presentViewControllerFrom:self];
}
From OverViewController (not presenting but adding subview) :
- (void)presentViewControllerFrom:(RootViewController *)sender
{
[sender presentViewController:self.base animated:NO completion:nil];
self.view.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.0];
self.view.opaque = NO;
[self.base.view addSubview:self.view];
}
This time, the transparency is great but any touch on the overView button cause a EXC_BAD_ACCESS to show up.
There I am, wondering how to do this. Any help will be greatly appreciated ! :)
Don't use a combination of presenting a view controller and adding subviews. Choose 1. It should be subview that you choose. It can be owned by another controller and that controller should probably be added as a child view controller.
In your first situation you see black because iOS is removing the (now expected to not be visible) view from the view hierarchy. So your view is transparent but what you expect to be behind it is no longer there.
Your second situation is probably just resulting in an invalid view hierarchy somewhere.
The overview controller should not own the base controller. The base controller should be shown and then the overview controller view added as a subview.
I'm trying to build the interface for an app that looks like this:
I want to use the Storyboard to create the views, but I'm having trouble figuring out how now. I've dropped a SplitViewController that is hooked up to 2 navigation controllers: MasterNavigationController, and DetailNavigationController (Master is the left side menu and Detail the right side).
I was starting to build all my ViewControllers in storyboard. Then build NSArrays to hold the various ViewController stacks needed for each of the Master's menu items. So when a user taps on a menu item, I'd load the corresponding ViewController stack into the DetailNavigationController using this method:
- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated
But now I'm thinking, I should create a separate DetailNavigationController for each of the menu items. For example:
RecentOrdersNavigationController
CustomersNavigationController
ItemsNavigationController
...
Then when a user taps a menu item, the entire DetailNavigationController changes to the appropriate one.
How should I be structuring the the interface while using storyboard?
Use a separate viewController for each detail view. You want your code to be separate since it can get confusing fast with all the different functionality for each view. From there, you can easily swap out the the detail.
Subclass UISplitViewController and set your root splitViewController to that class. Then add this method to your UISplitViewController subclass:
-(void)setDetailControllerTo:(UIViewController *)detailController withNavControllerTitle:(NSString *)title {
[detailController view]; // this line forces the viewDidLoad method to be called
if (title) {
UINavigationController *navController = [[UINavigationController alloc] init];
[navController pushViewController:detailController animated:YES];
detailController.title = title;
NSArray *viewControllers=#[self.mainController.viewControllers[0],navController];
self.mainController.viewControllers = viewControllers;
} else {
NSArray *viewControllers=#[self.mainController.viewControllers[0],detailController];
self.mainController.viewControllers = viewControllers;
}
}
To call this method do something like this from the master view controller in the tableView:didSelectRowAtIndexPath: method
FixedSplitViewController *splitController = (FixedSplitViewController*) self.splitViewController;
CurrentEventViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"CurrentEventViewController"];
// add any setup code here
[splitController setDetailControllerTo:controller withNavControllerTitle:#"Current Event"];
If you wish to keep the master view visible in portrait rotation, add this method to the SplitViewController subclass:
-(BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation {
return NO;
}
A lot of my projects require the splitviewcontroller to always show the master view so I use this subclass to keep the master view from hiding on portrait rotation.