Jesper Martensson
Jesper Martensson

Reputation: 1248

Using AutoLayout in Xcode disables my code from working (dynamically)?

In my project I have enabled AutoLayout in order to make the app scale properly in both iPhone 4 and iPhone 5. Everything worked fine with doing so, but I found a new problem which I am not sure how to handle.

In my project I have a normal method which checks if a boolean is yes or no, if yes the interface should add a button into the interface and keep my tableView in its current state. But if the method returns no, the button should disappear and make the tableView's height higher! Everything with the button works fine but for some reason after start using AutoLayout my code for increasing the tableView's height stopped working (which worked before).

Now what can I do to make my tableView's height increase in height even if I am using AutoLayout? Here is my code:

- (void)viewWillAppear:(BOOL)animated
{
NSString *bookName = [self getCurrentBookName];

if([self isBlank:bookName])
{
    [self.currentBookLabel setText:NSLocalizedString(@"LabelNoBookChosen", nil)];
}
else
{
    [self.currentBookLabel setText:[self getCurrentBookName]];
}

[super viewWillAppear:animated];

  if([self isAppLicensed] != YES)   <------------------THIS IS WHERE I CHECK THE BOOLEAN METHOD!
{
    [actionAppStore setHidden:TRUE];

    CGRect framez =  [tableView frame]; <------------------ THIS CODE IS NOT WORKING ANY LONGER!
    [tableView setFrame:CGRectMake(framez.origin.x, framez.origin.y, framez.size.width, framez.size.height+77)];
}    
else
{
    [actionAppStore setHidden:FALSE];
}
}

Upvotes: 0

Views: 3136

Answers (2)

Guillaume Algis
Guillaume Algis

Reputation: 11006

You probably need to tell the view to layout its subviews using layoutIfNeeded.

See my question I just solved and this question is also related.

Upvotes: 1

Rob
Rob

Reputation: 437432

You can either

  1. Turn off autolayout and use the autosizing masks. The non-autolayout autosizing masks give you the same control over having controls increase or decrease their size for the 3.5" screen vs the 4" screen. This is probably the easiest solution. And it gives you compatibility with iOS 5 devices, too.

  2. If you want to use autolayout, then you should create an IBOutlet for the appropriate constraint, and then programmatically change that.


On that latter example, consider a layout where I have a table view and a control at the bottom for the app store (I'm inferring this from your variable names). There are two ways to hide and show that bottom control. One is to hide it (or set its alpha to zero or to removeFromSuperview), remove the unnecessary constraints, and recreate the new appropriate constraints.

That works, but it's a hassle. I now prefer to either change the height of what I want hidden to zero, or, if it's already on the edge of the screen, I'll just slide it off the edge so you can't see it anymore.

Thus I might visually hide the app store control, not by playing around with it's hidden property, but rather by changing its height to zero (or, to show it, to 77). That way, the other constraints will automatically resize the other controls. Thus I hide it with:

        self.appStoreHeightConstraint.constant = 0.0;
        [self.view layoutIfNeeded];

And I show with:

        self.appStoreHeightConstraint.constant = 77.0;
        [self.view layoutIfNeeded];

I do that with an IBOutlet called appStoreHeightConstraint which is linked to the height constraint for that bottom control.

Alternatively (and only if the item being hidden is at the bottom), I can slide the it off the bottom of the screen (this time with a IBOutlet on the bottom constraint), with:

        self.appStoreBottomConstraint.constant = 77.0;
        [self.view layoutIfNeeded];

and show it with

        self.appStoreBottomConstraint.constant = 0.0;
        [self.view layoutIfNeeded];

In the interest of full disclosure, I should mention that you have to be very careful about designing the constraints so that they simultaneously (a) minimally describe your layout; but (b) fully describe your layout. You want to avoid the horrid conflicting or unsatisfactory constraint messages.

Focusing on the vertical dimension only, that means that have the following constraints:

  • table view's top constraint was to the top of the superview;
  • table view's bottom constraint was to the top of the app store view;
  • table view should have no height constraint (because that's what you want to change as other stuff changes);
  • the app store control at the bottom had it's top constraint linked to the tableview;
  • the app store's bottom constraint linked to the bottom of the superview; and
  • the app store's height constraint fixed at 77.0.

But I find that IB always (in a good faith effort to ensure that the constraints are unambiguous) is trying to add additional constraints (e.g. the height of the tableview). So, I personally wrestle with IB to get the constraints quite right (usually I end up lowering the priority of the table view height and when I'm all done with everything else, I can go back and get rid of the table view height).

Maybe I'm making too much of the hassles in editing the constraints, but I mention it because if you don't get them all exactly right, efforts to effect UI changes by altering one constraint will not yield the results you want. Once you get the hang of it, it's pretty easy and it's a thing of beauty to see everything adjust accordingly (esp on complicated scenes). But it can be a hassle to do those first few times.

Upvotes: 3

Related Questions