简体   繁体   中英

iPhone - UIViewController not rotating when device orientation changes

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]]; 

just do this if you what to rotate from landscape to portrait!

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

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.

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; eg 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM