I'm having some strange behavior where my MPMoviePlayerViewController isn't auto-rotating when the orientation changes. However, I recreated the same view hierarchy in a fresh project and when the MPMoviePlayerViewController player was up, it rotated to every orientation. I've scoured the project looking for anything that might be setting the orientation explicitly, but there is nothing.
I'll lay out all the relevant information here and the things that I've tried so far.
The view hierarchy currently looks like this:
Navigation Controller
"Root" View Controller <- navigation controller's 'rootViewController'
"Feed" View Controller <- Pushed on the navigation stack by the Root VC
"Preview" View Controller <- Presented as a modal VC from the Feed
MPMoviePlayerViewController Subclass <- presented by the Feed VC via 'presentMoviePlayerViewControllerAnimated'
Every class in the view hierarchy responds to shouldAutorotateToInterfaceOrientation with YES only for UIInterfaceOrientationPortrait.
Things I've tried:
Manually sending the shouldAutorotateToInterfaceOrientation up stack from the "Root" VC up to the MPMoviePlayerViewController
Overriding the MPMoviePlayerViewController subclass' implementation of shouldAutorotateToInterfaceOrientation to return YES for both landscape orientations and YES for all orientations.
Setting 'Supported Device Orientation' in the project's summary tab.
Calling the presentMoviePlayerViewControllerAnimated from other VCs like the Feed VC
If the movie player properly rotates in a fresh project with same view hierarchy, what could possible be getting in the way here. Any ideas as to where the orientation might be getting stuck?
I will suggest you not to use presentMoviePlayerViewControllerAnimated, rather than add as subview. I think it will fix your problem nicely.
MPMoviePlayerViewController *mpviewController = [[MPMoviePlayerViewController alloc]
initWithContentURL:[NSURL fileURLWithPath:self.filePath]];
[self.view addSubview:mpviewController.view];
[self setWantsFullScreenLayout:YES];
And remove the mpviewController.view when MPMoviePlayerPlaybackDidFinishNotification detected. Let me see your success...
I've found that MPMoviePlayerViewController objects will honor the project's Info.plist settings for supported interface orientations. In a project of mine I was only allowing landscape views in that file so the movie player will not rotate, even when it answered YES to landscape orientations in shouldAutorotateToInterfaceOrientation:.
Edit: OK, grasping at straws: Do you implement automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers in any of your UIViewController subclasses? If so, and it returns NO, your subclasses must forward the appropriate methods to any child controllers upon orientation change.
Otherwise is there any way to see your code?
I know this might be a stupid suggestion but make sure that the shouldAutorotateToInterfaceOrientation method in your MPMoviePlayerViewController subclass is getting called. Maybe something went wrong there...
Also make sure that you don't have 2 subviews added to the main UIWindow as specified here:
Q: Why won't my UIViewController rotate with the device?
[...]
The view controller's UIView property is embedded inside UIWindow but
alongside an additional view controller.
I think that might give you some problems too. You can find more information about what could go wrong in the link above.
A few ideas:
Is the UINavigationController set as the rootViewController property of your app's UIWindow? You didn't mention that. You should do this rather then adding the navigation controller's view to the window.
In case you are building the entire hierarchy at once, try breaking it down. You can add a button to each stage which adds the next view controller to the hierarchy.
Try removing any animations from the view controller hierarchy construction. Doing multiple animations at the same time could be trouble. For example, it's not allowed to push two view controllers in a UINavigationController one after another, with animated:YES. You might have a similar issue.
Make sure you build your entire view controller hierarchy on the main thread.
Make sure there is no other view controller "taking charge" of the rotation (as #MihaiFratu wrote - this is so common a reason for rotation issues that I had to repeat it :-) ).
Solution:
For anyone that might encounter this, the reason the video wasn't rotating was that I was accidentally adding the RootViewController has the window's rootViewController, rather than the UINavigationController.
self.window.rootViewController = navController;
is correct
self.window.rootViewController = rootViewController;
is not
Thank you guys for your help and input along the way.
Are you using storyboards? Compare the orientation settings for your UIViewControllers and your UINavigationController between your broken project and your test project. The "Orientation" setting on the attributes inspector may be locking you into one orientation.
You mentioned shouldAutorotateToInterfaceOrientation: and your plist settings so I won't get into that...
there are some reasons behind at your query..
***You are calling MPMoviePlayerViewController.. so apply AutoOrientation on "Feed" View Controller And try to call by PushViewController..
***Use MPMoviePlayerController instead of MPMoviePlayerViewController and add subview in to FeedViewController..
Sample code for MPMoviePlayerController--
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"filename" ofType:#"type"]];
videoPlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];
videoPlayer.controlStyle = MPMovieControlStyleNone;
videoPlayer.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.height, self.view.frame.size.width);
[videoPlayer prepareToPlay];
videoPlayer.view.center = self.view.center;
videoPlayer.fullscreen = YES;
[self.view addSubview:videoPlayer.view];
[videoPlayer play];
***Check your Xcode target setting and apply enable All orientation..
I had a similar problem.
Solved by:
enabling all orientations in Supported Interface Orientations (Target > Summary)
now your app will start rotating in all Orientations, if you dont want this, then skip step 1, only add following method in appDelegate
(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
return UIInterfaceOrientationMaskAll;
}
removing shouldAutorotateToInterfaceOrientation everywhere
adding following method to view controller for supporting Orientations u needed for your app
(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
you can add the same method as in step 4 in MPMoviePlayerViewController's subclass for whatever Orientations u needed for video player
You should try this (Worked for me):
Declare in .h file:
BOOL landscape;
.m file:
-(IBAction)PlayMovie:(NSString *)movieName {
landscape = YES;
NSBundle *bundle = [NSBundle mainBundle];
NSString *moviePath = [bundle pathForResource:movieName ofType:#"mp4"];
NSURL *movieURL = [NSURL fileURLWithPath:moviePath];
MPMoviePlayerController *theMovie = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
theMovie.scalingMode = MPMovieScalingModeAspectFill;
[theMovie play];
MPMoviePlayerViewController *moviePlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:movieURL];
[self presentMoviePlayerViewControllerAnimated:moviePlayer];
}
-(void)dismissMoviePlayerViewControllerAnimated {
landscape = NO;
[self dismissModalViewControllerAnimated:YES];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// You can change the return for your needs.
if (landscape == YES) {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
} else { return NO; }
}
What I did here is Creating my movie view and set the "landscape" BOOL to YES.
Then the "shouldAutorotateToInterfaceOrientation" will detect this and autorotate your view.
And when the movie is finished I set the "landscape" to NO so that the view rotates back.
this guide helped me checking some steps I was missing in order to allow only the video player to be viewed in landscape, leaving the rest of the application to be fixed in portrait mode:
iOS6 and autorotation tip
I had lot of pain with MPMoviePlayerViewController, which should be only controller able to rotate from portrait to landscape and vice versa. It was iOS7, iOS8 application with storyboard.
Here is solution:
Application should enable all possible required orientations
Every UIViewController that need to support just portrait mode, should implement next methods, like this
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
MPMoviePlayerViewController should be extended and next methods should be overriden like this
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
Use presentMoviePlayerViewControllerAnimated to display MPMoviePlayerViewController
Add this method in AppDelegate.m
-(NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if(!ISIPAD)
{
if ([[self.window.rootViewController presentedViewController] isKindOfClass:[MPMoviePlayerViewController class]] && ![[self.window.rootViewController presentedViewController] isBeingDismissed])
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
else
{
return UIInterfaceOrientationMaskPortrait;
}
}
return UIInterfaceOrientationMaskAllButUpsideDown ;
}
Related
I want all view controllers to support only portrait mode, except one view controller lets call it "LandscapeSupportViewController" that should support also landscape mode.
The problem is when I'm in LandscapeSupportViewController in landscape mode and then push a new view controller that only support portrait mode, the pushed view controller will be in landscape mode also! How could I force it to be portrait?
I saw few apps that do it, take for example Skype iPhone app, the Messages tab is portrait only -> then if you press to enter the message itself you get a view controller that support landscape also because it make sense to enable landscape mode when user is chatting -> then if you press to view the persons profile, a new view controller will be pushed but in portrait! the same happen if you go back, you will forced to return to portrait even if you came from landscape...
Thanks
I'd had students try to accomplish exactly what you are trying to accomplish, and after much research, the general consensus is: this is a bad idea and requires a lot of (App Store legal) hacks to accomplish, and still doesn't turn out too pretty (status bar, for example, screws up). You'll notice in the Skype app that when you go into the IM section, rotate to landscape, and hit back, the UI "snaps", or sort of gets instantly reloaded.
This is not a good user experience, and I'd recommend rethinking your design to be more in line with what Apple recommends.
If i got you correctly you want to change device orientation in some conditions.
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationPortrait animated:NO];
set your own orientation using above line, just put this lines inside the if condition. condition is depends on you.
Thank you!!
Write this lines before you push viewController which supported only portrait From landscapeViewController
[appdel.navigationController.view removeFromSuperview];// This navcontroller used with rootviewcontroller
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
[ [UIApplication sharedApplication].self.delegate.window addSubview:appdel.navigationController.view];
self.navigationController.navigationBar.hidden=NO;
Here is a solution.
You can add a category for UINavigationController which manages the view controller orientation. See code below:
#interface UINavigationController (MyViewOrientations)
#end
#implemetation UINavigationController (MyViewOrientations)
- (BOOL)supportLandscapeModeForViewController:(UIViewController *)controller {
return [controller isKindOfClass:[LandscapeSupportViewController class]]
}
- (NSUInteger)supportedInterfaceOrientation {
UIViewController *controller = [self visibleViewController];
NSUInteger orientationMasks = UIInterfaceOrientationMaskPortrait
if([self supportLandscapeModeForViewController:controller]) {
orientationMasks |= UIInterfaceOrientationMaskLandscapeLeft;
orientationMasks |= UIInterfaceOrientationMaskLandscapeRight;
}
return orientationMasks;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
UIViewController *controller = [self visibleViewController];
if([self supportLandscapeModeForViewController:controller]) {
return UIInterfaceOrientationLandscapeLeft; // Your call
}
else {
return UIInterfaceOrientationPortrait;
}
}
- (BOOL)shouldAutorotate {
UIViewController *controller = [self visibleViewController];
return [self supportLandscapeModeForViewController:controller];
}
#end
If the situation is more complex, different views support different orientations. You can override "supportedInterfaceOrientation", "preferredInterfaceOrientationForPresentation", "shouldAutorotate" in your view controllers, and delegate calls from UINavigationController category code with "visibleViewController".
I'm trying to get an app working in landscape mode which I've very nearly done, but for some reason the buttons on my view aren't working (ie. they don't press). I'm using a root view controller which loads the initial view controller as follows :
- (void)viewDidLoad
{
[super viewDidLoad];
StartViewController *viewController = [[StartViewController alloc] initWithNibName:#"StartView" bundle:nil];
self.startViewController = viewController;
startViewController.delegate = self;
[viewController release];
[self.view addSubview:startViewController.view];
}
I've also set the Initial Interface Orientation value in my Info.plist file and overridden the following in my root view controller :
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return((interfaceOrientation == UIInterfaceOrientationLandscapeRight) ||
(interfaceOrientation == UIInterfaceOrientationLandscapeLeft));
//return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
The view loads fine and fills the screen in landscape mode as it should, but for some reason I just can't press any of the buttons on the view.
I'm sure it's something simple related to me using a root view controller because I've managed to get this to work fine before with an app with just a single view controller.
Can anybody help me out here?
I think the problem is somewhere in xib.
E.g. the button is placed on UIView with incorrect resize masks. So that in landscape mode the button appears outside the view, and touches can't reach the button. You can check it setting clipSubviews in all the parent view -- if I'm right, you will not see the button any more.
I had a simular problem. In my case I was subclassing a UITableViewCell and I has overwritten the layoutSubviews method. In there I was doing translations. But I forgot to put the [super layoutSubviews]; before my implementation. After I put it htere, the button were working again in landscape mode. It was strange that in portrait it worked and in landscape not.
My app has about 10 different UIViewControllers, just one of which I want to switch to landscape mode if the device is rotated. (All the rest, I want to keep in portrait.)
In order to implement rotation on that one view, I needed to implement its controller's 'shouldAutorotate' method and return YES. Since this view is accessed via a navigation controller, I also needed to create a subclass of UINavigationController that implements 'shouldAutorotate' and return YES.
This solution works, but too well. I find that all of the UIViewControllers I push onto my subclass of UINavigationController respond to rotation, even if I implement 'shouldAutorotate' and return NO. (Remember: I only want one particular UIViewController to respond to rotation, not every one in the navigation controller's stack.)
So, my question is: how do I best do this? All the solutions I can come up with seem 1) cumbersome, and 2) worse, don't seem to work.
Thanks very much.
when you implement UINavigationController, this class is your the parent that controls all the children viewControllers that will be pushed into the stack. Therefore, the RootViewController is the only controller that say Yes or No to autorotation. Even if, you are passing Yes to auto-rotation in children view controllers, they don't count!
This is the nature of UINavigationController. So to change it, you have two choices:
1- Manually manipulate it, which requires you to go through some cumbersome codes.
2- Change your design so that it is more compatible to UINavigationController. That single view that should rotate, should be get called by the RootViewController (not the Navigation Root View Controller -- they are named the same, but are totally different), the view that hosts NavController. And when the device rotates, it will either push the NavController to the view or the other.
3- The other method, which will also work, but is not recommended because it violates the concept of MVC, is that your NavController can listen to Notifications. That particular child view that CAN and SHOULD rotate can cast a notification -- e.g. rotateMe, and once the NavController hears it, it rotates.
As I said, it will work, but it violates the MVC model -- which is fine to Apple, but from programming perspective is not recommended.
If you need further explanation about either of them, please let me know.
I do this by having a root view controller (this could be a UITabBarController) and in it's viewDidLoad method i subscribe to rotation events:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(didRotate:)
name:#"UIDeviceOrientationDidChangeNotification"
object:nil];
Then in the didRotate: method i look at which view controller is visible when the rotation happened, and what orientation the phone is in:
- (void) didRotate:(NSNotification *)notification {
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
/*
DEVICE JUST ROTATED TO PORTRAIT MODE
orientation == UIDeviceOrientationFaceUp ||
orientation == UIDeviceOrientationFaceDown
*/
if(orientation == UIDeviceOrientationPortrait) {
/*
DEVICE JUST ROTATED TO LANDSCAPE MODE
*/
}else if(orientation == UIInterfaceOrientationLandscapeLeft ||
orientation == UIInterfaceOrientationLandscapeRight) {
}
}
Within that didRotate: you can look at which is the visible viewController and do what you want from there.
I present a modal view controller in landscape mode when a particular view controller is visible and the phone is rotated into landscape. If any other view controller is visible, i ignore the event.
I force my modal view controller to display in landscape mode in its viewWillAppear method - i can give anyone this code if they want it.
Hope this helps.
Dave
Returns YES on the navigation controller subclass only if [[navController topViewController] isKindOfClass:[RotatingViewController class]]
I have seen examples using the way you are doing it but couldn't get it to work properly. I found the better way to do it from Apples examples. Basically you implement a presentModalViewController and create another view. UIKit does a basic rotation animation and fades between the view. You have to implement the rotated view as a delegate class so it can call back to its calling class to dismiss it and update the orientation.
- (void)orientationChanged:(NSNotification *)notification
{
// We must add a delay here, otherwise we'll swap in the new view
// too quickly and we'll get an animation glitch
NSLog(#"orientationChanged");
[self performSelector:#selector(updateLandscapeView) withObject:nil afterDelay:0];
}
And then to display a landscape screen:
- (void)updateLandscapeView
{
PortraitView *portraitView = [[PortraitView alloc] init];
portraitView.delegate = self;
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView)
{
[self presentModalViewController: portraitView animated:YES];
isShowingLandscapeView = YES;
}
else if (deviceOrientation == UIDeviceOrientationPortrait && isShowingLandscapeView)
{
[self dismissModalViewControllerAnimated:YES];
isShowingLandscapeView = NO;
}
[portraitView release];
}
I have a UIView which is supposed to cover the whole device (UIWindow) to support an image zoom in/out effect I'm doing using core animation where a user taps a button on a UITableViewCell and I zoom the associated image.
The zooming is performing flawlessly, what I haven't been able to figure out is why the subview is still in portrait mode even though the device is in landscape. An illustration below:
I do have a navigation controller but this view has been added to the UIWindow directly.
You can read about some of the possible causes here:
Technical Q&A QA1688 - Why won't my UIViewController rotate with the device?
In your situation its probably the fact that you are adding the view as another subview to the window. Only the first subview gets the rotation events. What you can do is add it as a subview of the first window subview.
UIWindow* window = [UIApplication sharedApplication].keyWindow;
if (!window)
window = [[UIApplication sharedApplication].windows objectAtIndex:0];
[[[window subviews] objectAtIndex:0] addSubview:myView];
The problem
Beginning with iOS 6, only the topmost view controller (alongside the
UIApplication object) participates in deciding whether to rotate in
response to a change of the device's orientation.
https://developer.apple.com/library/content/qa/qa1688/_index.html
The solution
I have open sourced a pod named AGWindowView.
It will automatically deal with any rotation and framechanges so you won't have to worry about that.
The code
It supports any combination of SDK's and iOS system versions. The relevant code can be found here:
https://github.com/hfossli/AGWindowView/blob/master/Source/AGWindowView.m
I created a category on UIApplication that has a helper property and method for getting the first subview of the keyWindow. This is the view you want to overlay anyway. Now when you add a view that is managed by a UIViewController to that view, the shouldRotateToInterfaceOrientation: method is called.
UIApplication+WindowOverlay.h
#import <UIKit/UIKit.h>
#interface UIApplication(WindowOverlay)
#property (nonatomic, readonly) UIView *baseWindowView;
-(void)addWindowOverlay:(UIView *)view;
#end
UIApplication+WindowOverlay.m
#import "UIApplication+WindowOverlay.h"
#implementation UIApplication(WindowOverlay)
-(UIView *)baseWindowView{
if (self.keyWindow.subviews.count > 0){
return [self.keyWindow.subviews objectAtIndex:0];
}
return nil;
}
-(void)addWindowOverlay:(UIView *)view{
[self.baseWindowView addSubview:view];
}
#end
and here is how you would use it.
//at the top of the file...or in {yourproject}.pch
#import "UIApplication+WindowOverlay.h
//in a method:
UIView *view = [UIView new];
UIView *window = [UIApplication sharedApplication].baseWindowView;
view.frame = window.bounds;
[window addSubview:view];
//or
[[UIApplication sharedApplication] addWindowOverlay:view];
This is because as you mention your view has been added directly to the UIWindow, therefore when the method to rotate is called for the navigation controller nothing happens to the uiview. The UIView would rotate if it was a subview of the view controller view. If for some reason this cannot be done. Then you could override this method:
// This method is called every time the device changes orientation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
}
And every time your orientation changes also change your view orientation.
I had a similar problem with views being added directly to a window. Maybe this will help: Automatically Sizing UIView after Adding to Window
Another solution how I solved this problem.
Define the current Orientation:
#interface AJImageCollectionViewController (){
UIInterfaceOrientation _currentOrientation;
}
#end
Then check the orientation in the viewWillLayoutSubviews:
- (void)viewWillLayoutSubviews {
[self checkIfOrientationChanged];
}
- (void)checkIfOrientationChanged {
UIInterfaceOrientation newOrientation = [[UIApplication sharedApplication] statusBarOrientation];
BOOL newOrientationIsPortrait = UIInterfaceOrientationIsPortrait(newOrientation);
BOOL oldOrientationIsPortrait = UIInterfaceOrientationIsPortrait(_currentOrientation);
// Check if the orientation is the same as the current
if(newOrientationIsPortrait != oldOrientationIsPortrait){
_currentOrientation = newOrientation;
// Do some stuff with the new orientation
}
}
I have got my own custom UIViewController, which contains a UIScrollView with an UIImageView as it's subview. I would like to make the image to auto rotate when device orientation changes, but it doesn't seem to be working...
In the header file, I've got;
#interface MyViewController : UIViewController <UIScrollViewDelegate> {
IBOutlet UIScrollView *containerView;
UIImageView *imageView;
}
These components are initialised in the loadView function as below;
containerView = [[UIScrollView alloc] initWithFrame:frame];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://..."]];
UIImage *image = [[UIImage alloc] initWithData:data];
imageView = [[UIImageView alloc] initWithImage:image];
[image release];
[containerView addSubview:imageView];
And I have added the following method, assuming that's all I need to make the view auto-rotate...
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
MyViewController loads fine with the image I've specified to grab from the URL, and the shouldAutorotate... function is being called, with the correct UIInterfaceOrientation, when I flip the device too.
However, didRotateFromInterfaceOrientation method do not get called, and the image doesn't seem to rotate itself...
Could someone please point out what I need to add, or what I have done wrong here?
Thanks in advance!
This may not be the right answer for you, because you don't specify the context that the UIViewController's in, but I just found an important gotcha in the Apple documentation that explains the similar problem I'm having.
Tab bar controllers support a portrait
orientation by default and do not
rotate to a landscape orientation
unless all of the root view
controllers support such an
orientation. When a device orientation
change occurs, the tab bar controller
queries its array of view controllers.
If any one of them does not support
the orientation, the tab bar
controller does not change its
orientation.
I've noticed that there are issues when rotating a UIView that's not the first or only view as a direct child of the main window.
So if your UIView is part of a Navigation Controller or a Tab View Controller, you'll also need to override shouldAutoRotateToInterfaceOrientation on the Navigation Controller or Tab View Controller.
Also: using [UIApplication setStatusBarOrientation] helps to work around things if/when you need to do it manually.
To make this kind of thing work in my application, I had to override
- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
[self layoutSubviews];
}
and also layoutSubviews
- (void)layoutSubviews
{
NSLog(#"layoutSubviews called");
...recalc rects etc based on the new self.view.bounds...
}
I'm not sure that this is absolutely required, but it worked for me.
Sometimes, if you add a subview to a view, it's your responsibility to make sure that the methods are passed to the subview; a couple of days ago I wrote a short post about this. For example, if you have a UIViewController and add a UINavigationController as subview, you must add this code to the UIViewController if you want viewWillAppear:animated: to be called when UINavigationController.view appears:
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[projectNavigationController viewWillAppear:animated];
}
It might be the case that the willRotateToInterfaceOrientation and didRotateFromInterfaceOrientation method also need to be called by the superview; I am not really sure about this, but give it a try.
This is discussed in Apple Technical Q&A QA1688.
Sometimes if you stack multiple views on top of each other for some reason, the anotherController might not receive rotation event.
[myWindow addSubview:primaryViewController.view];
[myWindow addSubview:anotherController.view];
A lazy way (not a good design) to fix this is only add one subview on window, but initialize multiple controller on the app delegate. Then when you need to switch window, remove the current view and add the view you want
[self.view removeFromSuperview];
AppDelegate *dg = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[[dg window] addSubview:[[dg viewController] view]];
I just came across this having a similar problem. I have a series of view controllers/complex views, that all rotate perfectly and couldn't figure out why the new one I just added on wasn't rotating. After a LOT of trial and error, the reason was that I wasn't calling the init method (it's the standard init method) when allocating the view controller;
e.g. I was doing
m_timerViewController = [TimerViewController alloc];
instead of
m_timerViewController = [[TimerViewController alloc] init];
To expand on jonoogle's post. I had a similar error. My view has a nib and my custom init:
- (id)initWithCategory:(Category *)category inManagedObjectContext:context{
didn't include the call to init the nib.
self = [super initWithNibName:nil bundle:nil];
Adding that line made my view rotate like it is supposed to.
I copied this from this link
And it works for me.... Reason why i have added this here is to make it easy for others to find. It took me many hours to find this fix:
Make a new set of class files of the UIViewController type, go into the .h file of this class and change this line
#implementation MyTabBarController: UIViewController {}
#end
to something like this
#implementation MyTabBarController: UITabBarController{
}
Now go into the nib file and click on the UITabBarController object and go to it's identity tab, and make it Class MyTabBarController.
now in MyTabBarController.m make sure this is in it.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)io {
return YES;
}
You can probably get rid of everything else in there if you want.
just do this if you what to rotate from landscape to portrait!
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}