在viewDidLoad或viewWillAppear中更改NSLayoutContraint常量不起作用

时间:2013-06-28 16:56:06

标签: ios autolayout viewdidload viewwillappear

我正在尝试做这样的事情:

- (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];
}

但有时这项工作有时并非如此。我总是在日志中看到正确的消息:

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

为什么会这样?如何在UI变为可见之前更改NSLayoutConstraints属性?

更新

这段代码20次20次(但我现在总是这样认为):

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

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

告诉我为什么会发生这种情况?

更新2:

看起来之前的代码仍无法正常工作,但这样做有效:

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

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

更新3:

我永远不会将相同的优先顺序(如500)设置为连接视图的几个约束......

1 个答案:

答案 0 :(得分:1)

我注意到你的优先级为500,这意味着你愿意打破这个约束以满足其他约束。我想知道你有什么其他限制。如果在Interface Builder中执行此操作,它会产生一种恼人的倾向(至少在Xcode 4.6.x中),以添加它认为需要的任何约束以消除歧义。您可能希望检查是否没有其他高度限制,或者优先使用的顶部和底部约束。

最重要的是,你设置constant的技巧很好(想想,我发现只使用setNeedsLayout就足够了)问题可能还有其他可能会持续存在的约束。

如果将此约束的优先级更改为1000,如果存在冲突约束,则会出现错误,这有助于诊断问题。但事实上,你告诉自动布局,如果忽略这个高度约束而支持其他冲突约束(优先级更高或相同),则可以。通过将优先级设置为1000,您可以说您绝不希望忽略此约束。