Code, Code, Revolution!
iPhone 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!
With this blog I try to provide useful tips and solutions for programming .NET, Objective-C and more. My name is Björn Sållarp, and I love writing code.
It's now available on AppStore. It's free and open source. Read more about the app here: Swedish / English
Find the device orientation using the accelerometer | blog.sallarp.com
May 7th, 2009 at 9:58 pm
[...] application where I use shouldAutorotateToInterfaceOrientation. Recently I wrote a post about the changes made to shouldAutorotateToInterfaceOrientation which in my opinion breaks important functionality. As promised here’s how you can replace [...]
OS3.0のshouldAutorotateTo-InterfaceOrientationがおかしい件 | iphoneアプリで稼げるのか
May 10th, 2009 at 9:54 am
[...] iPhone OS 3.0 – Breaking changes to shouldAutorotateToInterfaceOrientation | blog.sallarp.com Find the device orientation using the accelerometer | [...]
Andrew Borland
May 19th, 2009 at 3:04 am
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.
Björn Sållarp
May 19th, 2009 at 7:10 am
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.
Neoos
May 20th, 2009 at 11:05 pm
It’s actually pretty easy to solve: see http://www.neoos.ch/news/46-development/109-iphone-os-30-and-the-new-shouldautorotatetointerfaceorientation-behaviour
jurg
June 30th, 2009 at 10:07 am
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..?
Björn Sållarp
June 30th, 2009 at 3:54 pm
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
jurg
July 7th, 2009 at 8:19 am
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?
jurg
July 7th, 2009 at 2:28 pm
It’s okej, i think i solved it :]
baj
July 21st, 2009 at 12:34 pm
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
mobibob
October 27th, 2009 at 2:01 pm
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
mobibob
October 27th, 2009 at 2:03 pm
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
jb
January 16th, 2010 at 12:09 am
Thanks! I was pulling out my hair on this…