Greetings everyone.
I am currently working through the Beginning iOS 4 Application Development book and have come across a problem with the second Try It Out in Chapter 7.
Code:
-(void) positionViews
{
UIInterfaceOrientation destOrientation = self.interfaceOrientation;
if (destOrientation == UIInterfaceOrientationPortrait ||
destOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
//—-if rotating to portrait mode—-
btn.frame = CGRectMake(20, 20, 233, 37);
}
else
{
//—-if rotating to landscape mode—-
btn.frame = CGRectMake(227, 243, 233, 37);
}
}
The offending code is in bold. If you run the code sample as is provided in the book (I did not download the samples provided for the book so I am not sure if they are correct) when you rotate the simulator into landscape mode the button will stay at position 20,20 and then when you rotate the simulator back to portrait mode the button moves to 227,243! Basically this is happening is because self.interfaceOrientation contains the Orientation of the
previous view!
The reason this is happening, I believe, is because positionViews is being called to early. There are two possible solutions to this. The first would be to call positionViews like this:
Code:
-(void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[self positionViews];
}
The only problem with this is that it will actually animate the views as they reposition themselves which I found to be highly annoying. This was my solution to correct the problem (relevant code only from ScreenRotationsViewController.m displayed):
Code:
-(void)positionViews:(UIInterfaceOrientation) currentOrientation {
UIInterfaceOrientation destOrientation = currentOrientation;
if (destOrientation == UIInterfaceOrientationPortrait || destOrientation == UIInterfaceOrientationPortraitUpsideDown) {
btn.frame = CGRectMake(20, 20, 233, 37);
}
else
{
btn.frame = CGRectMake(227, 243, 233, 37);
}
}
- (void)willRotateToInterfaceOrientation: (UIInterfaceOrientation) toInterfaceOrientation
duration:(NSTimeInterval) duration
{
[self positionViews:toInterfaceOrientation];
}
- (void)viewDidLoad
{
[self positionViews:self.interfaceOrientation];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
The magic is in the bolded code above: toInterfaceOrientation contains the orientation that the simulator is going to which then permits the code in positionViews to execute correctly.
If it matters I am running Xcode v4.2 with my deployment target set to 5.0 (I have not downloaded the latest Beta yet).
If anyone has any questions please let me know.
-Doug
edit: I have also submitted this to the errata.
edit 2: This is for the iOS 5 version of the book that was published in January of 2012.