interface orientation not correct in presented view controllers in iOS 8 - ios

in iOS 7 and earlier, I was able to make UI changes in viewDidLayoutSubviews like so:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
if ( UIInterfaceOrientationIsLandscape(self.interfaceOrientation) ) {
//update views for landscape
}
else {
//update views for portrait
}
}
I can still do this in iOS 8 except in view controllers that are presented by other view controllers. When a view controller is presented by another view controller, this does not work, because the self.interfaceOrientation property is not correct in the presented view controller. It does not reflect the current orientation, but rather the orientation right before the device rotation.
The issue is not present if presenting a view controller on iPad with modalPresentationStyle set to UIModalPresentationPageSheet. In other words, the issue is only present when presenting a full screen view controller.
Any suggestions?

Try using this instead:
[[UIApplication sharedApplication] statusBarOrientation]
Also, if you are dropping support for iOS 7 and going 8-only, I recommend you drop interface orientation handling in favor of trait collections and size classes, if you can.

Related

UISplitViewController doesn't work on iPhone(5 nor 6)

On iPad, I have perfectly working UISplitViewController.
I can hide and show its primaryViewController, and splitViewController:willChangeToDisplayMode: is called in appropriate way.
But on iPhone, something is wrong.
I can show primaryViewController, but cannot hide it, because the primaryViewController appears in full screen size. It's so full that I can't touch the secondary view, in that way I can hide the primaryViewController on iPad.
splitViewController:willChangeToDisplayMode: is not called either.
I have a viewDidLoad below, in my custom UISplitViewController class.
// UISplitViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.delegate = self;
self.preferredPrimaryColumnWidthFraction = .1;
CGRect mainScreen = [[UIScreen mainScreen] bounds];
self.minimumPrimaryColumnWidth = 270;
self.maximumPrimaryColumnWidth = mainScreen.size.width - 5;
}
On iPhone, any of these property seems not to be working: preferredPrimaryColumnWidthFraction or minimum/maximumPrimaryColumnWidth
I am adding this splitViewController as rootViewController in AppDelegate.m by the code below.
// AppDelegate.m
[_splitViewCon addChildViewController: tagNaviCon];
[_splitViewCon addChildViewController: mainNaviCon];
self.window.rootViewController = _splitViewCon;
I searched web and found some keywords like "container view".
Is this something I have to do with, when I want to use a UISplitViewController on iPhone ?
I also watched WWDC Video, but I didn't understand "how to code it exactly".
Currently, I do not use any Interface Builder. So I'd be rather glad if someone gives programmaticaly way to code it.
Thank you !
You can have side-by-side UISplitViewController on iPhones 4S, 5, 5S and 6 as well.
To do it you have to embed its view in another view controller (addChildViewController:...didMoveToParentViewController:)
After that you'll be able to control split's behaviour by overriding its trait collection (setOverrideTraitCollection:forChildViewController:). Basically here you have to inspect your current trait collection and change the horizontal size class to regular. This way the UISplitController will be able to show both master and detail views (primary and secondary now called) by setting split's preferredDisplayMode
Then on rotation you can make the same observations about your trait collection and change the preferredDisplayMode and override again if necessary the split's trait collection. This can be done in viewWillTransitionToSize:withTransitionCoordinator: or willTransitionToTraitCollection:withTransitionCoordinator:. The second one won't be called on an iPad as its size classes are alway regular on both orientations.
One note about a problem I'm still not able to resolve. On iPhone 5S for example when rotating in portrait I'm hiding the master controller so to have only one view on the screen and the UISplitViewController should adapt itself to a UINavigationController. That works fine however during the rotation animation the master view is disappearing and you can see a blank ugly space.
One other note as well.
You have to implement UISplitViewControllerDelegate and use methods in order to set which view controller should be visible on app launch and when split is used as a navigation.
Here is a thread about this.
Hope it helps and if I find solution about the problem I have I'll update my answer
The #user1006806 answer worked for me. Here's how I got rid of the ugly blank space during the rotation from within my UISplitViewController's rotation method (iOS 8):
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
UIInterfaceOrientation theOrientation = [[UIApplication sharedApplication] statusBarOrientation];
if (UIInterfaceOrientationIsPortrait(theOrientation)) {
self.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;
} else {
self.preferredDisplayMode = UISplitViewControllerDisplayModeAutomatic;
}
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
self.preferredDisplayMode = UISplitViewControllerDisplayModeAutomatic;
}];
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
}

iOS Rotation with UITabBarController - switch controller out completely and smoothly

I have an iOS application and the main entry point into the storyboard is a Tabbar with with tabs. I want to support rotation but in landscape mode, each tab will look drastically different to the point I need to change the views out with others from the storyboard. At first though, I considered just switching out the entire tab bar controller when the user rotates, but I don't see how that might be accomplished. So I have two options that I can't seem to get anywhere with.
Switch each view with a segue somehow into it's landscape alternative and back. I've seen this done easily with modal views, but not with UITabbar before.
Switch out the entire tab bar somehow from the delegate so that I just have two completely separate section of my storyboard that are alike except one path is portrait and the other is landscape.
Does anyone have anything similar they are doing and could throw me a bone?
You can create a custom class for both view controllers, link them together with segoes, and then use didRotateFromInterfaceOrientation: to trigger the segues from code.
Create a class for your VC's. Add this code to the .m file:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
if (fromInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || fromInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
[self performSegueWithIdentifier:#"rotateToPortrait" sender:nil];
} else {
[self performSegueWithIdentifier:#"rotateToLandscape" sender:nil];
}
}
And in your storyboard, create segues between the two views. Make their identifiers "rotateToPortrait" and "rotateToLandscape", respectively. The code you added will switch the views whenever the device is rotated.
EDIT: I think I misunderstood the question. If you want to move views around, change their size, etc. when the screen is rotated, while keeping the same navigation/tab bar state, then you can do something like this in the didRotateFromInterfaceOrientation method:
if (fromInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || fromInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
myView.frame.origin.x = aNumber;
myView.frame.size.width = anotherNumber;
// Changing the layout of the views here by resetting their origins and sizes.
// This code is called when rotated from portrait to landscape.
} else {
// Do the same thing as above, but this one handles rotation from landscape to portrait.
}

UIView added on top of window does not rotate on iOS

I have a tabBar based application and want to present some custom view above whole screen (not as modal view) and I do it like that:
[self.view.window addSubview:self.myViewController.view];
The reason I did this is because this way view is positioned above UITabBar.
Anyway view is presented nicely and it covers whole screen like I want to. But there is a problem. When I rotate device this top view does not rotate, but view's underneath do.
I've tested on iOS5 and iOS6 without luck. Have also put this code in delegate:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskAll;
}
Similar code is in myViewController's view:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
The view just doesn't rotate... ?
As far as i know only the first subview of the window gets the rotation events. You're adding another view (your view) to the window and therefore need to deal with propagating the rotation events yourself.
Providing some really quick-help for you, just check out the following implementation : AGWindowView (not maintained from 2016)
You can set the rootController for your UIWindow.
e.g:
fileprivate(set) var bottonOverlayWindow = UIWindow()
self.bottonOverlayWindow.rootViewController = self;
// 'self' will the ViewController on which you had added UIWindow view. So whenever you ViewController change the orientation, your window view also change it's orientation.
Let me know if you face any issue.

Interface Orientation with TabBarController

I am using a Tab Bar Controller in my app. In the most part of the app's behavior we have one single orientation (interfaceOrientationPortrait). But i have a view that runs a video in WebView. When i am running this video, the orientation remains portrait. I want to put for all orientations.
Well, i used the return type YES in my Video's class. Nothing has changed. I changed the return type to YES in my RootViewController class. Nothing has changed.
I would like to change the orientation only for the Video.
View controllers that are part of a tab bar controller won't rotate to an orientation if any of the tab bar controllers can not rotate to that orientation (at least if the tab bar is visible). So maybe you want to update all your controllers' method in order to let the rotation happen if the web view controller is visible on the tab bar controller.
If you need a deeper explanation, just ask. Good luck!
Edit (example code)
This is what could be your rotation methods for your tab bar controller view controllers:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if ((self.tabBarController.selectedIndex == kMyWebViewControllerIndex))
{
return YES;
} else
{
return (orientation == UIInterfaceOrientationPortrait);
}
}
Is your web view in a view controller inside the tabBarController?
Try showing it in a modally presented view controller, it should work

Why is [UIViewController presentModalViewController:animated:] transitioning the modal view in from the left?

I'm building an application that supports only Landscape orientation on the iPad under iOS 4.3, though the bug was present under iOS 4.2 as well.
Several places in the application, I am showing UIViewControllers as modal views. All of them are shown using this pattern:
viewController.modalPresentationStyle = UIModalPresentationFormSheet;
viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:viewController animated:YES];
In most places, they work as expected - the modal form sheet slides in from the bottom of the screen upward.
However, in two cases, the modal form sheet slides in from the bottom left of the screen. The form sheet slides nearly all the way to the right with the bottom of the form sheet out of view. If you focus a text field and show the onscreen keyboard, the form sheet moves to the top center of the screen where you would expect it to be.
I don't think the Simulated Metrics of the XIBs affect their behaviour, but I have set the orientation for all of them (both the calling UIViewController self and the modal view controller viewController) to Landscape.
Any ideas why these two modal form sheets are behaving differently from the others?
I think here you dint return landscape orientation in shouldAutorotate function so use this code if you wan view as landscape left/right:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight||interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
// return YES;
}
Try this it may help you..
Make sure if you have a viewController embedded in a NavigationController that the navController shouldAutotorate is also set to landscape

Resources