使用自动布局移除和重新添加子视图

9
使用自动布局时,我理解的是在移除一个子视图时(当然要持有对它的引用),被移除的子视图仍然知道它的自动布局约束条件。
然而,当稍后将其添加回超级视图时,子视图不再知道其框架大小。相反,它似乎得到了一个零大小的框架。
我以为自动布局会自动调整大小以满足约束条件,但事实是否如此?我认为自动布局意味着不要干扰框架矩形。即使使用自动布局,我是否仍需要设置子视图的初始框架矩形?
1个回答

16

删除子视图时,与该子视图相关的所有约束都会丢失。如果您稍后需要再次添加子视图,则必须重新为该子视图添加约束。

通常情况下,我会在自定义子视图中创建约束。例如:

-(void)updateConstraints
{
    if (!_myLayoutConstraints)
    {
        NSMutableArray *constraints = [NSMutableArray array];

       // Create all your constraints here
       [constraints addWhateverConstraints];

       // Save the constraints in an ivar. So that if updateConstraints is called again,
       // we don't try to add them again. That would cause an exception.
       _myLayoutConstraints = [NSArray arrayWithArray:constraints];

       // Add the constraints to myself, the custom subview
       [self addConstraints:_myLayoutConstraints]; 
   }

   [super updateConstraints];
}

updateConstraints会被Autolayout运行时自动调用。上面的代码应该放在你自定义的UIView子类中。

在使用Autolayout时,确实不需要改变frame大小。相反,只需在updateConstraints中更新约束即可。或者更好的方法是,设置好约束,这样就不必再去更新了。

请参考我在那个主题上的答案:

Autolayout UIImageView with programatic re-size not following constraints

你不需要设置初始frame。如果你使用initWithFrame,只需将其设置为CGRectZero即可。你的约束将详细说明某些东西应该有多大,或者其他关系,这意味着运行时可以推断出大小。

例如,如果你的可视格式是:@"|-[myView]-|",那么这就是你在水平方向上所需要的一切。Autolayout将知道将myView的大小调整到父superview的边界上,由|表示。这很酷。


1
谢谢。很明白易懂。我想提醒一下,我问的是Cocoa而不是Cocoa-touch,但其他人需要注意的是,这两个API(正如Apple的Peter Ammon所描述的)基本相同。因此在两个世界中的方法应该是相同的。 - uchuugaka
1
文档说明(https://developer.apple.com/Library/ios/documentation/UIKit/Reference/UIView_Class/UIView/UIView.html#//apple_ref/occ/instm/UIView/updateConstraints)指出,在实现过程中调用`[super updateConstraints]`作为最后一步是非常重要的。它应该放在方法的结尾,而不是开头。 - Eric
是的,我认为这是在iOS7中引入的。现在已经更新,谢谢。 - Max MacLeod
你是指CGRectZero吗?我无法评论NSView,但我想它的工作方式应该是相同的。使用自动布局,你应该使用约束而不是框架。调用[[UIView alloc] init]将创建一个CGRectZero视图,与initWithFrame:CGRectZero相同。 - Max MacLeod
1
我一定是困了。确实,initWithFrame可以接收它并正常工作。 - uchuugaka
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接