UISplitViewController as a segue target - ios

I have a UIViewController. A button on the UIView should bring the user to a UISplitViewController. I'm using a segue for that, setup using the storyboard UI.
While some answers here seem to suggest this might not work (UISplitViewController has to be the root - or does this mean something different?), this does indeed work. Except - The SplitViewController on iPhone always starts with its DetailView, not with the MasterView.
What can be done about that?

As far as I know you cannot use splitViewControllers with iPhones, so you will have to use separate code to handle the iPhone version of your app(unless they have released something recently enabling this).
You could say
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
// Show your master view
} else {
// Present normally
}

Related

Display view modally in ipad and push in iphone

UIViewController has to be presented modally in iPad while the same should be pushed in iPhone. Is there any support for the same by apple by default ?
You have to detect the device and perform tasks accordingly.
if UIDevice.current.userInterfaceIdiom == .pad {
//present modally
} else if UIDevice.current.userInterfaceIdiom == . phone {
//push
}
As already mentioned you will need to do this manually. You can check what device you are having and decide how to present your view controller.
But this usually produces a huge issue and can greatly increase complexity of your application. Since you are in one case presenting and in other case pushing a view controller you will also need to pop or dismiss it. This can easily be solved by adding some extra properties but then later on it might interfere again when you want to dismiss a whole navigation stack or similar. Not to mention problems with deep linking.
So if possible I would try to avoid having different view controller hierarchy depending on device. If possible I would try to simply change the animations (I assume that is all that you need). Maybe this will help.

tab bar on iPhone, but not on iPad

I'm developing a universal app.
The overall design is to have tab bars on iPhones, but not on iPads.
I've been trying to use size class, but found no luck.
Some example apps are MLB At bat and EBates, they have tab bars on the iPhone version but not on the iPad one.
How should I achieve this?
To hide tab bar in a specific iPad view(s). In your viewdidload method.
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
self.tabBarController.tabBar.hidden=YES;
}
You could create a custom class of UIViewController and put this method in if you have many or a mixture of controllers that require this behaviour. You don't mention the specific behaviour you require
or
In your in your navigation controller (if you're creating one) use myController.hidesBottomBarWhenPushed = YES. If you're creating one in your AppDelegate for instance it would hide the tabbar throughout the views that are in the hierarchy of the navigationController (any view unless you use another navigationController in your app)
MyController *myController = [[MyController alloc]init];
// Hide tab bar for all app
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
myController.hidesBottomBarWhenPushed = YES;
}
[self.navigationController pushViewController:myController animated:YES];
You could always subclass your navigationController to achieve the same if you're using interface builder to achieve the same behaviour
You have not stated what language you're using Objective C or swift. Tagging your question with the language would be useful. The auto layout tag is irrelevant as this is nothing to do with autolayout

Using splitviewcontroller on iPhone portrays detail view first

I'm currently developing for iOS 8 and developing an app with the new adaptive framework. The weird part is when I use the the splitviewcontroller on iPhone with this storyboard configuration the app does not start with the master view controller but the detail controller. Is this a bug and how could I be able to fix it?
This does only happen if the navigationController that envelops the master exists, if I remove it the app starts with master controller.
The thing to realise is that when a split view controller app starts on iPhone 6 Plus in portrait, it is just showing the split view controller in its collapsed state. By default this has the detailed view pushed above any view controllers in the primary navigation controller.
The way to stop a particular view (such as a blank detail view you may initially show on iPad) from being displayed at launch, or indeed after any rotation to portrait, is to handle this in the splitViewController:collapseSecondaryViewController:ontoPrimaryViewController: delegate method. This will be called at launch on iPhone or iPhone 6 Plus in portrait before presentation.
Doing this, you shouldn't need to have any device specific code.
In its simplest form this would look like:
- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController
{
if ([secondaryViewController isKindOfClass:[BlankViewController class]])
{
// If our secondary controller is blank, do the collapse ourself by doing nothing.
return YES;
}
// Otherwise, use the default behaviour.
return NO;
}
Obviously, you then need to do the reverse in splitViewController:separateSecondaryViewControllerFromPrimaryViewController: to create and return a BlankViewController for the new secondary view if you don't want your topmost primary view controller to end up on the detail side after split view expands.
Be aware mixing your own implementation with Apple's in these methods, they do some crazy stuff like embedding UINavigationControllers inside other UINavigationControllers. See my related answer here: https://stackoverflow.com/a/26090823/4089333
UPDATE: Michael Wybrow's answer is better.
I ran into this issue and found this to work:
splitViewController.viewControllers =
UIScreen.mainScreen.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact ?
#[ leftNavigationController ] :
#[ leftNavigationController, rightNavigationController ]
;
And in the splitview delegate:
- (UIViewController *)primaryViewControllerForCollapsingSplitViewController:(UISplitViewController *)splitViewController
{
return leftNavigationController;
}
- (UIViewController *)primaryViewControllerForExpandingSplitViewController:(UISplitViewController *)splitViewController
{
return leftNavigationController;
}
- (UIViewController *)splitViewController:(UISplitViewController *)splitViewController separateSecondaryViewControllerFromPrimaryViewController:(UIViewController *)primaryViewController
{
return rightNavigationController;
}
It's horrible, I know. But it does the right thing, especially on the iPhone 6 Plus, which is very tricky to get right.
UPDATE: Michael Wybrow's answer is better.
It is probably an error due to the SplitViewController being just exclusive to the iPad. Also when you have it in the portrait orientation, it displays the detail view by default and the master view will show as a bar. You will have to change it using some method like splitViewController:shouldHideViewController:inOrientation
Here is an Apple document referring your problem
https://developer.apple.com/library/ios/documentation/uikit/reference/UISplitViewController_class/Reference/Reference.html
I hope this helps!

How to support multiple screen orientations in iOS 7 without pushing another view controller on the stack?

I have been trying to get multiple orientations to work with a single view controller. Currently it checks for the device orientation and view controller. Then switches based on whether it's landscape or portrait. The problem is that it works fine in portrait, but since it pushes another view on the stack whenever it's in landscape the back button links to the portrait view instead of the actual screen we want to get back to (which is one further step away).
if (UIDeviceOrientationIsLandscape(deviceOrientation) &&
self.navigationController.visibleViewController == self)
{
self.landscapeViewController =
[self.storyboard instantiateViewControllerWithIdentifier:#"view_landscape"];
[self.navigationController pushViewController:self.landscapeViewController
animated:NO];
}
else if (UIDeviceOrientationIsPortrait(deviceOrientation) &&
self.navigationController.visibleViewController == self.landscapeViewController)
{
[self.navigationController popViewControllerAnimated:NO];
}
I cant present the landscape view controller in modal fashion, since there is a navigation controller involved.
Another thing is that I'm instantiating the same view controller for each orientation (using the same class but linking to different identifiers in the storyboard).
The thing you're trying to do is REALLY bad and goes against Apples way of doing things.
There's something called Autolayout, with which you can design a single view to work both in landscape and portrait mode.
It is possible you can handle programatically or simply use auto-layout depends on your requirement .just prefer this LINK

iPad Landscape not resizing SubViews correctly

I am writing an iPad application using MonoTouch, MonoDevelop and Interface Builder, and i've stumbled across a problem that I can't seem to solve. It is probably something simple. What I am trying to do is force an application to Landscapemode from start. The application starts in Landscape, but doesn't resize the subviews correctly.
Basically what I am doing in my appdelegate is that I add a SubView called IndexViewController.xib to Window. In IndexViewController I have a View with a Label on it, if I then in IndexViewController override the ShouldAutorotateToInterfaceOrientation to return this: it works correctly.
public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
{
return ((toInterfaceOrientation == UIInterfaceOrientation.LandscapeLeft) || (toInterfaceOrientation == UIInterfaceOrientation.LandscapeRight));
}
However, I now try to create a NavigationController and add it to the IndexController.xib-view on the Initialize:
void Initialize ()
{
this.View.AddSubview (NavController.View);
}
It rotates correctly but doesn't fill the entire "window", I have posted a screenshot and a sample solution. And my info.plist is set to allow "UIInterfaceOrientationLandscapeLeft" and "UIInterfaceOrientationLandscapeLeftRight" as UISupportedInterfaceOrientations
Screenshot
Sample solution here
There is probably something dead simple simple that I am missing, but I can't figure it out.
I'd say this may be due to the fact the way you're building the app's hierarchy isn't the suggested way of doing so. While you could carry on this way, you'll encounter more problems down the road.
Ideally you want to be adding the NavigationController's View the window rather than the having the NavigationController contained within a UIViewController.
In the app delegate, I would do something along the lines of:
IndexViewController indexVC = new IndexViewController()
UINavigationController navController = new UINavigationController(indexVC);
window.AddSubview(navController.View);
This will add the navigation controller's view to the window, with the RootViewController of the NavigationController being your IndexViewController
You should also remove the UINavigationController that is added to your IndexViewController in Initialise().
I just downloaded your sample solution and tried this very quickly and it loaded the app in Landscape with the view fully filling the screen. It didn't auto rotate, but this'll certainly be a good starting point for you :)

Resources