4

I am trying to do something like this:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    NSLog(@"%@", self.tableViewHeight);
    self.tableViewHeight.constant = 0;
    NSLog(@"%@", self.tableViewHeight);

    [self.tableView setNeedsUpdateConstraints];
    [self.tableView setNeedsLayout];
    [self.view setNeedsUpdateConstraints];
    [self.view setNeedsLayout];
}

But sometimes this work and sometimes not. I always see right messages in log:

<NSLayoutConstraint:0x9ebe7a0 V:[UITableView:0xa345a00(304@500)] priority:500>
<NSLayoutConstraint:0x9ebe7a0 V:[UITableView:0xa345a00(0@500)] priority:500>

Why this happens? How to change NSLayoutConstraints properties before UI became visible?

UPDATE:

This code works 20 times of 20 times (but I think now always):

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    dispatch_async(dispatch_get_main_queue(), ^{
        self.tableViewHeight.constant = 0;
        [self.view setNeedsUpdateConstraints];
    });
}

Just tell me why this happens really?

UPDATE 2:

Looks like previous code still not working but this works:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    self.topViewHeight.constant += self.tableViewHeight.constant;
    self.tableViewHeight.constant = 0;
    [self.view setNeedsUpdateConstraints];
}

UPDATE 3:

I WILL NEVER SET EQUAL PRIORITIES (LIKE 500) TO SEVERAL CONSTRAINTS WITH CONNECTED VIEWS...

k06a
  • 17,755
  • 10
  • 70
  • 110

1 Answers1

1

I notice that you have a priority of 500, which means that you're willing to break this constraint in order to satisfy other constraints. I wonder what other constraints you have in place. If doing this in Interface Builder, it has an annoying tendency (in Xcode 4.6.x at least) to add whatever constraints it thinks it needs in order to eliminate ambiguity. You might want to check that you don't have other height constraints, or top and bottom constraints that are taking precedence.

Bottom line, your technique for setting the constant is fine (thought, I find just using setNeedsLayout is sufficient) and the problem probably rests with other constraints that might be lingering about.

If you change the priority of this constraint to 1000, if you have conflicting constraints you'll get an error as to what they are, which is helpful in diagnosing the problem. But as it is, you're telling autolayout that it's ok if this height constraint is ignored in favor of other conflicting constraints (of greater or equal priority). By setting the priority to 1000, you're saying that you never want this constraint to be ignored.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • I have aligned vertical UIView and UITableView, both have height constraints with priority 500 and vertical spacing constraint equal to 0. So I would like to hide my UITableView on app start... – k06a Jun 28 '13 at 18:01
  • 1
    @k06a If you have incompatible constraints of equal priority, but a priority less than 1000, I don't believe that you're guaranteed which constraint will "win". I can imagine all sorts of internal implementations of autolayout that might change the "winner" based upon the timing of the setting of the `constant`, but I wouldn't personally rely upon that. IMHO, I'd make the priority of your constraints ensure a predictable pattern, rather than relying on an idiosyncrasy enjoyed by deferring of setting of the constraint `constant`. It will "future-proof" your app. – Rob Jun 28 '13 at 18:21