程序化自动布局、约束和 UIView 运行时

Posted

技术标签:

【中文标题】程序化自动布局、约束和 UIView 运行时【英文标题】:Programatic autolayout, constraints and UIView runtime 【发布时间】:2013-02-03 22:05:37 【问题描述】:

在阅读 Apple 的 View Programming Guide 时,很明显他们没有针对约束进行更新。所以有几个问题:

    这里的许多帖子都谈到了在初始化新 UIView 或将其设置为 CGRectZero 或其他等效项时不使用 -initWithFrame。那你会怎么处理呢?:

    -(id)initWithFrame:(CGRect)frame
    
        self = [super initWithFrame:frame];
        if (self)
    
        //Set up rounded rectangle ivar
        CGRect frame = [self bounds];
        CGFloat radius = frame.size.height / 2;
        _rectPath = [UIBezierPath bezierPathWithRoundedRect:frame cornerRadius:radius];
         
    
    

    然后将绘图代码放入drawRect:中。我发现没有框架就无法正确初始化。 (显然,我正在初始化这个 UIView 并立即设置约束但没有立即设置框架)。此代码集的 frame = (0,0,0,0) 因为尚未计算约束。

    如果我们不把这段代码放在 init 中,我们会把它放在哪里?另外,我认为在 init 的视图中初始化我们需要的所有东西是一种很好的做法。

    所以这就引出了问题……

    在运行时周期中何时调用 -updateConstraints 以及视图何时使用这些约束计算其边界?我注意到在-layoutSubviews 之后视图真的不知道它的边界是什么。如果 UIView 仅设置了约束,那么在此之前是否还有其他地方知道它的边界?

很抱歉所有问题,但它们似乎都有关联。感谢您的关注。

【问题讨论】:

【参考方案1】:

您的框架问题与自动布局无关。视图大小一直在变化。它几乎与对象实例化期间不同。您需要创建/计算路径的大小以适应当前大小 drawRect,而不是在您第一次创建视图时。

您应该在init 期间设置的唯一对象是您的类的其余部分依赖于以某种状态存在的属性和/或 ivars。

【讨论】:

好的,这是有道理的。我想我想表达的观点是,有时您需要边界信息,而使用自动布局时,您并非一直都可以使用。事实上,似乎很少。我真的很想知道系统在什么时候计算边界? 我不确定系统何时在自动布局下计算边界。但是,当您对视图进行子类化时,这并不重要。您只知道何时调用drawRect:,您需要显示当前边界(或只是dirtyRect)。如果边界更改对您的实现非常重要,请覆盖 setBounds

以上是关于程序化自动布局、约束和 UIView 运行时的主要内容,如果未能解决你的问题,请参考以下文章

使用自动布局约束在 UIScrollView 内为 UIView 设置动画

UIView 使用约束自动布局居中和调整大小

Swift UIView 自动布局和约束

在自定义 UIView 类 Iphone 上应用自动布局约束。

使用自动布局约束时,UIView 无法通过 UIpangesture 顺利拖动

自动布局和 AVPlayerViewController