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

Posted

技术标签:

【中文标题】使用自动布局删除和重新添加子视图【英文标题】:Removing and re-adding a subview with autolayout 【发布时间】:2013-06-21 06:12:36 【问题描述】:

当使用自动布局时,我的理解是删除一个子视图(当然同时持有对它的引用),被删除的子视图仍然知道它的自动布局约束。

但是,稍后将其添加回超级视图时,子视图不再知道其帧大小。 相反,它似乎得到了一个零帧。

我假设自动布局会自动调整大小以满足约束。不是这样吗? 我认为自动布局意味着不要弄乱框架矩形。添加子视图时是否还需要设置初始框架矩形,即使使用自动布局?

【问题讨论】:

【参考方案1】:

删除子视图时,与该子视图相关的所有约束都将丢失。如果以后需要再次添加子视图,则必须再次向该子视图添加约束。

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

-(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 时,您不想触及帧大小。相反,只需更新updateConstraints 中的约束。或者,更好的是,设置约束,这样您就不必这样做了。

查看我对该主题的回答:

Autolayout UIImageView with programatic re-size not following constraints

您不需要设置初始帧。如果您确实使用initWithFrame,只需将其设置为CGRectZero。您的约束将 - 事实上必须 - 详细说明某物应该有多大,或其他关系意味着运行时可以推断出大小。

例如,如果您的视觉格式是:@"|-[myView]-|",这就是水平维度所需的一切。自动布局将知道将myView 的大小调整到由| 表示的父superview 的边界。挺好看的。

【讨论】:

谢谢。这很好,很清楚。我问了一个关于 Cocoa 而不是 Cocoa-touch 的注释,但其他人要注意的是,API(如 Apple 的 Peter Ammon 所述)相同或几乎相同。两个世界的方法应该是一样的。 The documentation 表示调用[super updateConstraints] 作为实现的最后一步是重要。它应该在你的方法结束时,而不是在开始时。 是的,我认为这是在 ios7 中引入的。现在更新了谢谢 不幸的是,我没有看到 NSView 处理 CGZeroRect 或 NSZeroRect 和 UIView 一样好......请告诉我我在想象。 (请注意标签) 我一定是困了。确实 initWithFrame 可以接收并正常工作。

以上是关于使用自动布局删除和重新添加子视图的主要内容,如果未能解决你的问题,请参考以下文章

奇怪的 iOS 8 自动布局问题

使用自动布局进行编辑时在表格视图中调整子视图的大小

添加 UIView 并使用自动布局重新计算约束

使用自动布局调整同级视图的大小时,使用子视图重新定位 UIView 不起作用

使用 Masonry 向视图的子视图添加自动布局约束

使用自动布局删除视图并重新排列其余部分