UIView rotate problem - ios

I have two UIViewController in my app. I switch the view between them. One is hidden other one is not. Everything goes fine except the orientation problem. In both UIViewController
I override this method
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return ((interfaceOrientation == UIInterfaceOrientationLandscapeRight)||
(interfaceOrientation == UIInterfaceOrientationLandscapeLeft));
//return YES;
}
and set orientation to landscape in both Xib files.
in ***Delegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
.......
viewController.view.hidden=TRUE;
[self.window addSubview:viewController.view];
[self.window addSubview:menuController.view];
.....
}
if I add viewController.view first viewController.view is landscape position and it can rotate to landscapeLeft or landscapeRight. But the menuController.view is still portrait position and the view cannot rotate at all.
if I add menuController.view first the situation is opposite.
Why this happened? How to fix this? My app is almost done. Is there any simple way to solve this problem without make big changes to my code.
Any suggestion is appreciated. Thank you very much!

Which view controller is being defined as the rootViewController for Window? When the device rotates, AFAIK, the view that is manipulated is the one at rootViewController.view.
You can check this putting an NSLog in each view controller's shouldAutorotateToInterfaceOrientation. If I'm right, you'll see only one call to this function.
Define which view controller should be the root, and present the other one modally, or use a navigation controller.
Hope it helps!

Related

Keeping the same orientation with Auto Layout

How can I keep the orientation of a view completely unchanged when the interface orientation changes, independently from the other views?
For example, if I have a tall blue view in portrait mode, I would like the view to remain oriented the same way when the interface switches to landscape mode. If I have any other views aside from this view, the other views should reorient as usual, and, also, the status bar should get reoriented as well. The only view that should not get reoriented is this blue view.
All I could do so far with Auto Layout was to resize and reorient the view, which is what I don't want to happen.
- (BOOL)shouldAutorotate;
- (NSUInteger)supportedInterfaceOrientations;
This should help you.
Also you may try to use
- (void)viewWillAppear:(BOOL)animated {
[[UIDevice currentDevice] setValue:#(UIInterfaceOrientationLandscapeLeft) forKey:#"orientation"];
}
Did you try overriding the NavigationController Class.
In that, Implement the supportedInterfaceOrientations methods.
-(NSUInteger)supportedInterfaceOrientations
{
UIViewController *vc = [[self viewControllers] lastObject];
Class clsSupportsSpecificOri = NSClassFromString(#"REQUIRED_CLASS");
if ([vc isKindOfClass:clsSupportsSpecificOrientation])) {
return UIInterfaceOrientationMaskLandscapeLeft;//Set your required orientation
}
else {
return UIInterfaceOrientationMaskAll;
}
}
This might helps you. As the supportedInterfaceOrientation method gets called every time a navigation occurs.

Launching into portrait-orientation from an iPhone 6 Plus home screen in landscape orientation results in wrong orientation

The actual title for this question is longer than I can possibly fit:
Launching an app whose root view controller only supports portrait-orientation but which otherwise supports landscape orientations on an iPhone 6 Plus while the home screen is in a landscape orientation results in a limbo state where the app's window is in a landscape orientation but the device is in a portrait orientation.
In short, it looks like this:
When it is supposed to look like this:
Steps to Reproduce:
iPhone 6 Plus running iOS 8.0.
An app whose plist supports all-but-portrait-upside-down orientations.
The root view controller of the app is a UITabBarController.
Everything, the tab bar controller and all its descendent child view controllers return UIInterfaceOrientationMaskPortrait from supportedInterfaceOrientations.
Start at iOS home screen.
Rotate to landscape orientation (requires iPhone 6 Plus).
Cold-launch the app.
Result: broken interface orientations.
I can't think of any other way to enforce a portrait orientation except to disable landscape altogether, which I can't do: our web browser modal view controllers need landscape.
I even tried subclassing UITabBarController and overriding supportedInterfaceOrientations to return the portrait-only mask, but this (even with all the other steps above) did not fix the issue.
Here's a link to a sample project showing the bug.
I had the same issue when launching our app in landscape on an iPhone 6 Plus.
Our fix was to remove landscape supported interface orientations from the plist via project settings:
and implement application:supportedInterfaceOrientationsForWindow: in the app delegate:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
Apparently the information in your plist is to specify what orientations your app is allowed to launch to.
Setting the statusBarOrientation of the UIApplication seems to work for me. I placed it in the application:didFinishLaunchingWithOptions: method in the app delegate.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
application.statusBarOrientation = UIInterfaceOrientationPortrait;
// the rest of the method
}
This appears to be a bug in iOS 8 when using a UITabBarController as a root view controller. A workaround is to use a mostly vanilla UIViewController as the root view controller. This vanilla view controller will serve as the parent view controller of your tab bar controller:
///------------------------
/// Portrait-Only Container
///------------------------
#interface PortraitOnlyContainerViewController : UIViewController
#end
#implementation PortraitOnlyContainerViewController
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
#end
// Elsewhere, in app did finish launching ...
PortraitOnlyContainerViewController *container = nil;
container = [[PortraitOnlyContainerViewController alloc]
initWithNibName:nil
bundle:nil];
[container addChildViewController:self.tabBarController];
self.tabBarController.view.frame = container.view.bounds;
[container.view addSubview:self.tabBarController.view];
[self.tabBarController didMoveToParentViewController:container];
[self.window setRootViewController:container];
I only want my app to open in landscape mode (and not exhibit the problem you describe above on the iPhone 6 Plus), so I set Landscape (left home button) and Landscape (right home button) as the only orientations allowed in my app's PLIST file. This fixes the orientation problem when my app opens. However, I need my app to support portrait mode for one view only since I display a UIImagePickerController in my app, which Apple requires to be shown in portrait mode on iPhone.
I was able to support portrait for that one view only, while keeping my app opening in landscape mode, by including the following code in AppDelegate:
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
return UIInterfaceOrientationMaskAllButUpsideDown;
} else {
return UIInterfaceOrientationMaskAll;
}
}
I had a very similar problem. I wanted to force portrait mode everywhere except for playing back videos.
What I did was:
1) to force the app orientation to be in portrait in the AppDelegate:
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if ([window.rootViewController.presentedViewController isKindOfClass:[MPMoviePlayerViewController class]])
{
return UIInterfaceOrientationMaskAll;
}
return UIInterfaceOrientationMaskPortrait;
}
2) launching an empty modal view controller fixed the problem in my case.
I launch it in the viewDidLoad of the first view controller that is on the root of my NavigationViewController (the first view controller visible after the application launches):
- (void)showAndHideNamelessViewControllerToFixOrientation {
UIViewController* viewController = [[UIViewController alloc] init];
[self presentViewController:viewController animated:NO completion:nil];
[viewController dismissViewControllerAnimated:NO completion:nil];
}
Please try the following code.
Probably this problem caused by size of keywindow on landscape launch.
// in application:didFinishLaunchingWithOptions: ...
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
[self.window setFrame:[[UIScreen mainScreen] bounds]]; //<- ADD!!
No luck for me the workaround by Jared using a generic container view controller. I've already subclassed tab bar controller with supportedInterfaceOrientations with no luck as well. Regardless of orientation of the 6+ after launch the tab bar's window is reporting frame = (0 0; 736 414)
So far the only workaround I've found is to force the window frame after makeKeyAndVisible
[self.window makeKeyAndVisible];
self.window.frame = CGRectMake(0, 0, MIN(CGRectGetWidth(self.window.frame), CGRectGetHeight(self.window.frame)), MAX(CGRectGetWidth(self.window.frame), CGRectGetHeight(self.window.frame)));
I got same bug on my app, I figured it out with this solution
Firstly it didn't work but after some dig I have to do it on initial controller after splash screen.
Answer is OjbC language let me update it to Swift
override var shouldAutorotate: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
Don't forget that should on the initial view controller.
For myself, I was having the same issue as jaredsinclair, but subclassing a UIViewController with the supportedInterfaceOrientations method was not solving the issue. Instead I did exactly what he did in my appDidFinishLaunching method of my AppDelegate and added my UITabBarController as a child to a normal UIViewController rather than his subclass and it worked!
I'm in the same situation, and doing [self.window setFrame:...] doesn't work for me.
Adding the following at the end of application:didFinishLaunchingWithOptions is the only thing I've found that works. It makes the screen blink and isn't exactly clean and efficient.
I added this at the end of application:didFinishLaunchingWithOptions:
UIViewController *portraitViewController = [[UIViewController alloc] init];
UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController:portraitViewController];
[self.navController presentViewController:nc animated:NO completion:nil];
[self.navController dismissViewControllerAnimated:NO completion:nil];
[UIViewController attemptRotationToDeviceOrientation];
I had a similar issue is with my app runs both in landscape and portrait with a UITabBarController as root view controller.
Whenever the app was launched when in Landscape mode, the view was incorrect.
All I had to do:
- remove rootview controller assignment in the XIB.
- Manually add it in once the app is launched:
(void)applicationDidFinishLaunching:(UIApplication *)application {
application.statusBarHidden = YES;
[self.window setRootViewController:self.tabBarController];
That fixed the problem.
Just Remove All the items in Supported interface orientation except what you want (i need only Portrait) in info.plist , it will work for me
just call
[application setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
in app delegate method
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
in fact the device now is UIInterfaceOrientationPortrait after Launching ,if you touch an inputField ,the keyboard is portrait layout

Setting orientation in iOS 7

I have th e following code in my uiviewcontroller.m file:
-(BOOL)shouldAutoRotate
{
return YES or NO;
}
I have tried both YES and NO but my view controller still rotates? I am using iOS 7 and the other iOS solutions I found aren't working for me either.
It probably happens because your controller instantiated as child of UINavigationController in view hierarchy. The UINavigationController does not query child controllers if they want to be rotated or not.
I had the same issue; I wanted to disable autorotation, so all hierarchy of particular UINavigationController is locked in Portrait. I ended with this class:
#implementation FixedOrientationNavigationController
- (BOOL)shouldAutorotate {
return NO;
}
#end
which I put instead of UINavigationControllr class in Storyboard for hierarchies which I need to lock Portrait. Just this, I do not need to implement shouldAutorotate in each controller.
You may also check this link: Orientation Respectful UINavigationController, it tries to implement "orientation respectful" UINavigationController.
It works, but in some cases it leads to weird results, for example, when user rotate to Landscape and then go back to the controller which should only support Portrait.
You can also set the orientation by clicking on project name and then general ,here you can set the orientations you want and set
- (BOOL)shouldAutorotate {
return NO;
}
Hope you got.

Tabbar controller with navigationcontrollers orientation ios 6

I'am currently working on an project where we have a tab bar controller with 4 tabs, and where each tab have an navigation controller. On each of these navigation controller there is multiple viewcontrollers pushed on it.
I read a lot of post here and other places, and we have currently done the following:
Subclassed UITabbarcontroller
- (BOOL)shouldAutorotate
{
return [[[self.viewControllers objectAtIndex:self.selectedIndex]topViewController] shouldAutorotate];
}
- (NSUInteger) supportedInterfaceOrientations
{
return [[[self.viewControllers objectAtIndex:self.selectedIndex]topViewController]supportedInterfaceOrientations];
}
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
return [[[self.viewControllers objectAtIndex:self.selectedIndex]topViewController] shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
}
This work fine, if we in each of our viewcontrollers specify the following:
- (NSUInteger) supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
return YES;
}
This will lock it to Portrait as expected.
But now the real problem occurs!
If we in our viewcontroller on one of the tabs specify that it should rotate to landscape it works fine, but when we then change tab it is still in landscape, which is not what we want!
So to sum up, have anyone got a solution to how you lock almost all views to a given orientation expect one, and can change tabs where they are in the orientation you specified (here portrait)?
I also read this post iOS 6 UITabBarController supported orientation with current UINavigation controller, but as one comment also mentioned "This is almost working for me. The problem is if I am already in landscape when I switch tabs to a portrait only view it is still in landscape. Rotating portrait fixes it and it won't rotate back to landscape, but I still need it be in portrait when it first loads" which almost is the same here..
I myself had this problem and i worked out a solution, its not pretty but it works.
In your TabbarController subclass implement this tabbarcontroller delegate function (remember to set delegate):
-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
int selected = self.selectedIndex;
UIViewController *con = [[UIViewController alloc] initWithNibName:#"XIBName" bundle:nil];
[[self.viewControllers objectAtIndex:selected] pushViewController:con animated:NO];
[[self.viewControllers objectAtIndex:selected]popViewControllerAnimated:NO];
[[self.viewControllers objectAtIndex:selected] setDelegate:nil];
}
The push and pop on the uinavigationcontroller in the tabs navigationcontroller will make the tabbarcontroller fire its Orientations functions again, and if you implemented the orientations code correctly it will change to your desired orientation.
i hope this helps, please fell free to comment if i need to explain anything in details.
Best Regards
Morten

iPad Modal View rotates parentViewController View

When the application is in landscape mode (which I plan to force), displaying a modal view causes the parent view to rotate to portrait mode. If I set the return value of shouldAutoRotateToInterfaceOrientation to NO, the parent does not rotate, however the modal then slides in from the side and displays sideways. Below is the code that reveals the modal.
- (IBAction)loadExistingGame:(id)sender {
SavedGamesTableViewController *savedGames = [[SavedGamesTableViewController alloc] initWithStyle:UITableViewStyleGrouped];
savedGames.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:savedGames animated:YES];
[savedGames release];
}
As per request here is the contents of the shouldAutoRotate method of the SavedGamesTableViewController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Override to allow orientations other than the default portrait orientation.
return YES;
}
Ok I figured out what needed to be done to fix it. The plist file that contains a list of the possible orientations needs to be limited to a single landscape view. The parent to the modal table view needs to have the shouldAutoRotateToInterfaceOrientation method return YES only if the orientation matches the only orientation in the plist file.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return interfaceOrientation = UIInterfaceOrientationLandscapeRight;
}
the modal viewcontroller should return NO for the same method.
Based on
When the application is in landscape
mode (which I plan to force),
displaying a modal view causes the
parent view to rotate to portrait
mode.
and
As per request here is the contents of
the shouldAutoRotate method of the
SavedGamesTableViewController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Override to allow orientations other than the default portrait orientation.
return YES;
}
So what you're saying is that the parent view controller is not yet set to force only using landscape orientation, and when you show a modal view that is set to allow all orientations, you're wondering why your parent view rotates to portrait when you rotate the device to portrait? I don't understand your question... aren't you saying that parent view controller is currently set to allow rotation to portrait? Isn't this behaviour exactly what should happen?
I had a similar problem when bringing up a modal mail view. Forcing the rotation didn't work for me, but calling presentModalViewController on the application's main view controller rather than a child view controller solved the issue.
I was seeing the same behavior; in my case the problem was I had implemented shouldAutorotateToInterfaceOrientation to return YES unconditionally for the parent view controller but NOT for the presented modal view controller. So I suspect Shaggy Frog's comment is the key: whether you want to force landscape mode or not, you need to make sure that the two view controllers' shouldAutorotateToInterfaceOrientation implementations agree or weirdness will ensue.
UIViewController *vc = /* create view controller */;
UINavigationController *nc = nil;
if (IOS_VERSION_LESS_THAN_6_0) {
nc = [[MyCustomNavigationControllerSupportingAllOrientations alloc] initWithRootViewController:vc];
} else {
nc = [[UINavigationController alloc] initWithRootViewController:vc];
}
[self.navigationController presentModalViewController:nc animated:YES];
On iOS6 I use a UINavigationController.
On pre-iOS6 I subclass UINavigationController, like this:
#interface MyCustomNavigationControllerSupportingAllOrientations : UINavigationController
#end
#implementation MyCustomNavigationControllerSupportingAllOrientations
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
#end

Resources