iPhone OS 3.0 – Breaking changes to shouldAutorotateToInterfaceOrientation

xcodeiPhone OS 3.0 beta 3 has been available for a few weeks and it’s actually pretty stable. The most annoying bug in the standard functionality must be that quite often the last row of buttons in phone mode disappear. A reboot fix that until next time it happens, but it’s annoying.

Unfortunately I haven’t had the time to mess around much with the new APIs in 3.0. I’ve tested my Hitta Hem application and found a breaking change to the shouldAutorotateToInterfaceOrientation which I use to rotate images in an UIScrollView. I’ve explained and posted that code. Since beta 1 of iPhone OS 3.0 shouldAutorotateToInterfaceOrientation doesn’t behave like in 2.x, which is a problem. In 2.x that event always fire, regardless, when you rotate the device. In 3.0 beta however, if you return false (don’t rotate) when you turn the divide to landscape, the even won’t fire again when the device is rotated back to UIInterfaceOrientationPortrait. If you return true when it was rotated to landscape, it will fire when it’s rotated back to UIInterfaceOrientationPortrait. The problem is of course that if you return true, the entire UI will rotate, and I don’t want to support the entire application in landscape. This is probably some kind of “optimization”, but I can’t imagine it’s a huge CPU saver to prevent one event from firing.

I’ve also found another bug/change that relate to this. If you inherit a UIViewController and retrieve the interface orientation using self.interfaceOrientation it will fire the shouldAutorotateToInterfaceOrientation event, so if you were to use that method inside the event reciever for shouldAutorotateToInterfaceOrientation, you’ll get an infinite loop.

Hopefully Apple will change this back to how it works in 2.x. I have sent in a bug report covering both these issues but haven’t got any replies on it. Of course the rotation can be solved using the accelerometer, I’ve already looked into it, and if there are no changes in the next beta I will try to post an updated solution.

*UPDATE*

Kyle posted a response to another post I made about determining the interface orientation using the accelerometer. It’s possible to listen to the UIDeviceOrientationDidChangeNotification event by attaching to NSNotificationCenter and get exactly the same fuctionality in 3.0 as in previous versions.

Attach to the event, this can be done at viewDidLoad, viewWillAppear etc:

-(void) viewWillAppear: (BOOL) animated{
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(receivedRotate:) name: UIDeviceOrientationDidChangeNotification object: nil];
}

Recieve the event:

-(void) receivedRotate: (NSNotification*) notification
{
   UIDeviceOrientation interfaceOrientation = [[UIDevice currentDevice] orientation];
   if(interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
   {
 
   }
}

Unregister from the event, this should be done when you don’t need the event anymore for example in viewWillDisappear:

-(void) viewWillDisappear: (BOOL) animated{
[[NSNotificationCenter defaultCenter] removeObserver: self];
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
}

Big thanks to Kyle for this code!

I’ve updated my original example with this code for iPhone OS 3.0. Check it out!

13 thoughts on “iPhone OS 3.0 – Breaking changes to shouldAutorotateToInterfaceOrientation

  1. I had this exact problem. Check to see if your subclass of UIViewController has an initWithFrame method like this:

    - (id)initWithFrame:(CGRect)frame {
    NSLog(@”Calling initWithFrame:”);
    [super init];
    return self;
    }

    I left out the [super init] line and it wouldn’t rotate. Added this in and everything worked fine. Again, this line wasn’t needed in 2.2.1, but in 3.0, obviously, they are doing something different.

  2. I did try adding code for initWithFrame, it didn’t help however. The rotate event fires when the phone is tilted left but when NO is returned, it will not fire the rotated event when tilted back to portrait. I tested this on iPhone OS 3.0 beta 5. Please share your code if you are certain that it works.

  3. sry i don’t quite get it, just another noob :]

    should I take all the code from:
    (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

    and add to

    -(void) receivedRotate: (NSNotification*) notification

    Could someone paste how it should look whit this project. Because when I do it, the images rotates up into the corners and all seems to be wrong..?

  4. Yes, move whatever code you have in shouldAutorotateToInterfaceOrientation to receivedRotate, or call your shouldAutorotateToInterfaceOrientation from receivedRotate if you like.

    What project are you referring to? If your image rotate you’re doing something at least :) .

    // Björn

  5. I refered to your example project, the name of the article is “shouldAutorotateToInterfaceOrientation”.

    yeah but to get it work with your code, what should I do? As I said before the images is rotating up in the corner. doesn’t yours?

  6. Thanks for the tutorial! Great one!!
    I tried adding a tool below the image. But a when the orientation is changed, the toolbar does not change its orientation.
    Could you pls tell me how to solve this.Thanks

  7. That worked for me! What a bug … that sounds like the Y2K bug as it could take down every app on the planet for no good reason.

    How did you know to look for it as a bug in the OS? I banged my head against the wall looking at my code for my syntax, usage, typo, etc. as a bug in my code. Wow – thanks!

    -@mobibob

  8. BTW – Baj, I am not 100% on this, but I think you have to code the header/footer views. I don’t recall the details, but their are methods to get called if you have such views. In your case your toolbar is a footer. Many of the other actions already account for your tool, nav and status bars.

    -mobibob

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>