I have a view controller which manages a view.
I'm adding the my view controller subclass as a subview of the window swapping out another view.
I'm running landscape mode on an iPad.
The view apparently doesn't know that its in landscape mode. Its frame is confused.
Is there something I can/should do to tell it that its in landscape, and/or that the orientation has changed. How does this normally happen. Why isn't it happening?
I used to have my view controller within a UITabBarController and it worked fine there.
Override:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return YES;
}
Your ViewController is not getting rotation events because you have not presented the viewController but have added the viewController's view in the view hierarchy.
Your Tab bar controller previously used to take the responsibility to forward the rotation events to the view controller which it manages, that was how it used to work.
I would though suggest that swapping the view out of window is a bad idea. Instead you should have a main viewController which accepts the rotation events and then swap the view within this viewController based on the current orientation. Consider re-desiging before you code further.
My problem was that my storyboard was overriding my existing custom coded app delegate. After I deleted the story board file, and custom generated view controller code, it worked for me.
Related
I'm trying to work with the iOS6 Auto-rotation mess.
I've looked at almost every single SO question relating to it, and no matter what I try, I can't get rotation working how I need it.
The app is using storyboards, and the layout is as follows:
Navigation controller ---> Root view controller ---> Tab view controller ---> View controller ---> Landscape view controller.
The view controller auto-rotates when I rotate the simulator, but when segueing back to the previous view (that is set to portrait), the view becomes landscape, when it should be portrait. If I rotate the simulator back, the view auto-rotates to portrait again, but this should've been done automatically!
I've implemented (UIInterfaceOrientation)preferredInterfaceOrientationForPresentationand it doesn't get called in any view controller I put it in.
I've subclassed the NavigationController to return the topViewController's shouldAutoRotate, supportedInterfaceOrientations and preferredInterfaceOrientationForPresentation and auto-rotation when rotating the simulator seems to work, but preferredInterfaceOrientationForPresentation never does its job.
Does anyone have a solution to this?
It would appear Apple have removed the ability to push a view in a specific orientation. preferredInterfaceOrientationForPresentation does get called, but only when popping back or presenting a view controller. I had to present my landscape view rather than push it, and set shouldAutoRotate = NO.
Refer to: In iOS6, trouble forcing ViewController to certain interfaceOrientation when pushed on stack for more details.
My app has a view controller hierarchy set up like this:
UITabBarController
|
UINavigationController
| |
| UIViewController
|
UINavigationController
|
UIViewController
All of my view controllers that are within this hierarchy override the method:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
and return YES - therefore the view controller should be able to rotate to any rotation - even upside down.
However, within this setup none of the view controllers successfully rotate. I was under the impression that navigation and tab bar controllers would rotate if their view controllers respond to rotating.
Why won't my view controllers rotate?
The only way I've been able to get them to rotate is by subclassing UINavigationController and overriding it's shouldAutorotate method, but this feels unnecessary to me and I was wondering if there's something I've missed to make this work.
Edit:
According to the User Experience Coding How-to:
If you are also using a toolbar, the view controller for each toolbar item must implement the shouldAutorotateToInterfaceOrientation: method and return YES for each of the orientations you wish to support. If you have a navigation controller for a toolbar item, the root view controller of that navigation controller must implement the shouldAutorotateToInterfaceOrientation: method and return YES.
It says 'toolbar' - but I think this is a typo and is probably supposed to be 'tab bar'.
So it seems that I'm implementing this correctly, yet my controllers still do not auto rotate.
I've run into this problem, but I can't remember the exact reason it occurred. The tab bar controller requires all of its view controllers to respond YES when asked about a particular orientation for it to rotate to that orientation.
If presented modally, it seems like it doesn't matter about the underlying VC system.
I have created a test to show this (RotationTest on GitHub), but it all seems to be working. Hopefully I can remember why I was failing with this one at some point.
Have you tried subclassing the Tabbarcontroller and setting it as your tabbarcontroller? In there, set
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
to
YES
The only way I've been able to get them to rotate is by subclassing UINavigationController and overriding it's shouldAutorotate method, but this feels unnecessary to me and I was wondering if there's something I've missed to make this work.
I don't know for sure if this is the wrong approach, but I would subclass the UITabBarController, sooner than the UINavigationController. Also, you can try wrapping everything in a subclassed UIViewController that implements the rotation method, but this will create the overhead of an extra view. I once tried to do rotation in an with UINavigationController, but it was not pretty. I suspect that the reason the views only rotate if you subclass the UINavigationController is that the view hierarchy will only pass the rotation if the parent rotates. If the parent doesn't rotate, the child won't. (Imagine an iPhone in a dock. The iPhone only can rotate if the dock rotates. Now, compare the dock to an iPhone case. The case can also rotate, so the iPhone will rotate too.)
It says 'toolbar' - but I think this is a typo and is probably supposed to be 'tab bar'.
I do not think that the HIG has a typo in that regard. The terms may interchangeable.
Generally, a "toolbar" is relevant to the view that contains it, and therefore should rotate with its parent view. A tab bar, however, is the "parent", so to speak, of the view controller on the screen. The view controller should therefore only rotate if the entire app rotates. This concept basically boils down to this: Which view (bar or view controller) is dependent on the other? (The tab bar is persistent, but the views change, or is the toolbar only there if the view is visible.)
Subclass the UITabBarController as well as the UINavigationController. It works as using xCode 4.4.
I have developed an extension that allows you to do just this without subclassing UITabBarController https://github.com/piercifani/TabBarBetterRotation
I have a subclass of UITabBarController which i am using so that i can rotate to use my app in landscape too.
How would i go about rotating my UI and getting each view controller to use a landscape view xib?
I have always just written apps before where returning YES for shouldAutorotate... handles it automatically for me... this isn't the case here now, as i'm using a custom view.
Thanks.
You don't need to subclass UITabBarController to get the autorotation behavior. Instead what you should do is have ALL the UIViewControllers that appear in your UITabBarController return YES for shouldAutorotateToInterfaceOrientation:. If even one of them does not, the UITabBarController will not autorotate.
As for the custom view, it is associated with a UIViewController, right? If so, then if your custom view implements layoutSubviews using the current view bounds to lay out all the subviews, then it should autorotate correctly as well.
I'm going in circles here. I have set shouldAutoRotateToInterfaceOrientation for all the view controllers. My app is running correctly in landscape, like this:alt text http://img517.imageshack.us/img517/3749/screenshot20100701at802.png
However, when I add a new subview using [window addSubview:whatever.view]; it shows up like this:alt text http://img291.imageshack.us/img291/3749/screenshot20100701at802.png
How can I make the new subview automatically be added in landscape orientation?
Thanks!
window is probably not managed by one of your view controllers that implement shouldAutoRotateToInterfaceOrientation.
Add your view to one of your view controllers that implement the autorotation.
Within Interface Builder, I have the following
UIViewController
-- View
---- TableView
In my UIViewController I have set
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
I also have other view controllers that are in IB. What am I missing here? The only way I can get it to rotate is if I use the transform method.
Are you using the tableview in a tab-based app by any chance? In case you are, you can only get a view to support landscape mode if all the viewcontrollers of the tabbar controller support landscape mode.
Other than that, I don't see any reason why your view should not support landscape mode.
The problem is with the autosizing settings. To be more specific, in Interface Builder, make sure autoresizing is clicked, then in the Size Inspector, make sure the tableview all it's superviews of the table view have red arrows filled in on the top, left, right, and also select the two internal arrows.
I am wondering if the questioner actually had the table view in a subview of the main view. I see this behavior for a table view that is one level deeper in the view hierarchy:
Main View
Subview
Table View
By default, the Main View has it's autosizing arrows set up correctly, but if you add an additional view, it does not.
In response to the question about the problem being with multiple view controllers: Note that a UIViewController is not a UIView's delegate. In fact, it looks like chain of events goes the other way - first the system sees an autorotation and tells the UIViewControllers about it. If the UIViewControllers have shouldAutoresize returning yes, then the UIViewControllers resize their main views. The resizing of the main views can automatically cause their subviews to resize if they are set correctly.
According to Apple docs, you should not have multiple view controllers controlling different parts of a view - for example a separate tableview controller for a table view that is in a subview of the main view - because it mucks with the event chain - you could see how that would be the case here. Don't know if that's helpful or not.
I just tried this, and it works as expected. You will need to provide more detail, I think. In my experience, when a view "fails" to rotate, that's because some view controller somewhere is telling it not to. Check to make sure all your view controllers are returning the right values from shouldAutorotateToInterfaceOrientation:
if your are using storyboard, your VC contains a UITableview, check if your Scene have AutoLayout unchecked.