Gold Challenge - moving the button back


#1

Hi - trying to figure out why is the button not restored to its original Y position when rotated back to portrait. I’ve created the button to be moved in the Designer (XIB file).

Funny enough when I print the buttonToMoveOriginalY value in the viewDidLoad it is exactly the same as when printed in the willAnimatedRotationToInterfaceOrientation method. Thought the button returns to a position that is approx. 100 points lower then the original position. Any suggestions how to fix this? Thanks, Jack

HeavyViewController.m


-(void)viewDidLoad
{
    //store the button original margin,width and center y position
    buttonToMoveMargin = [buttonToMove frame].origin.x;
    buttonToMoveWidth = [buttonToMove frame].size.width;
    buttonToMoveOriginalY = [buttonToMove center].y;
    NSLog(@"the button original Y is %f",buttonToMoveOriginalY);
}


-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)x
{
    //return YES if incoming orientation is Portrait
    //or either of the Landscapes, otherwise, return NO
    return (x == UIInterfaceOrientationPortrait) || UIInterfaceOrientationIsLandscape(x);
    
}

-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)x duration:(NSTimeInterval)duration
{
    CGRect bounds = [[self view] bounds];
    
    //if the interface rotates to Landscape do...
    if (UIInterfaceOrientationIsLandscape(x)) {
        [buttonToMove setCenter:CGPointMake(bounds.size.width-buttonToMoveMargin-buttonToMoveWidth/2, CGRectGetMidY(bounds))];
    } else //otherwise if the interface is back to Portrait then ...
    {
        [buttonToMove setCenter:CGPointMake(buttonToMoveMargin+buttonToMoveWidth/2, buttonToMoveOriginalY)];
        NSLog(@"the button original Y is %f",[buttonToMove center].y);

    }
}
-(void)viewDidLoad
{
    //store the button original margin and width
    buttonToMoveMargin = [buttonToMove frame].origin.x;
    buttonToMoveWidth = [buttonToMove frame].size.width;
    buttonToMoveOriginalY = [buttonToMove center].y;
    NSLog(@"the button original Y is %f",buttonToMoveOriginalY);
}


-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)x
{
    //return YES if incoming orientation is Portrait
    //or either of the Landscapes, otherwise, return NO
    return (x == UIInterfaceOrientationPortrait) || UIInterfaceOrientationIsLandscape(x);
    
}

-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)x duration:(NSTimeInterval)duration
{
    CGRect bounds = [[self view] bounds];
    
    //if the interface rotates to Landscape do...
    if (UIInterfaceOrientationIsLandscape(x)) {
        [buttonToMove setCenter:CGPointMake(bounds.size.width-buttonToMoveMargin-buttonToMoveWidth/2, CGRectGetMidY(bounds))];
    } else //otherwise if the interface is back to Portrait then ...
    {
        [buttonToMove setCenter:CGPointMake(buttonToMoveMargin+buttonToMoveWidth/2, buttonToMoveOriginalY)];
        NSLog(@"the button original Y is %f",[buttonToMove center].y);
        //the buttonToMoveOriginalY is exactly the same as when printed in the viewDidLoad
    }
}

#2

From what I understand (and I’m still learning here), you’re looking at two different object spaces. Your first location for OriginalY is based on the height of the UIView in your HeavyViewController.xib file (which is probably iPhone 5 height). When you run your application, the first time the simulator will put the object in the right location (independent if you’re using iPhone, iPhone 4 retina or iPhone 5).

When your orientation code is running though, all your calculations are now based off of CGRect bounds (which is going to be different depending on the iPhone device).

So my recommendation to you is when setting the portrait y location, like your landscape calculation, you just use CGRectGetMidY(bounds). That should put it back to the middle of the screen (providing that’s how you lined it up originally in the xib file).

The reason you currently see it in the wrong location is you’re putting it back in absolute space, which if the simulator is iphone or iphone 4, will be lower. Make sense?


#3

If it’s helpful, here’s my code:


- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)x duration:(NSTimeInterval)duration
{   
    CGRect bounds = [[self view] bounds];
    CGFloat xMargin = 20.0;
    // If the orientation is rotating to Portrait mode....
    if (UIInterfaceOrientationIsPortrait(x)) {
        [moverButton setCenter:CGPointMake(xMargin + moverButton.frame.size.width/2.0, bounds.size.height /2.0)];
    } else {
        [moverButton setCenter:CGPointMake(bounds.size.width - xMargin - moverButton.frame.size.width/2.0, bounds.size.height / 2.0)];
    } 
}

#4

I assume that “moverButton” is the name you’ve given the new button, but how do you name a button on the .xib (or any item for that matter)? I don’t see a “name” or “id” field when I click the Attributes inspector.


#5

You declare it in the header file like:

__weak IBOutlet UIButton *mover;

and then in the XIB interface you control drag the File Owner to the button and select the appropriate name you created. Go back to chapter 7 and take a look at figure 7.11 (as one example).