首先,我应该提一下,这主要是效率问题。
关于在viewWillAppear
过早而且viewDidAppear
太晚(视图已经可见)的框架计算在哪里进行的讨论很多。
常见的答案是在viewDidLayoutSubviews
中进行帧计算。问题是,它被多次调用。更糟糕的是,最准确的呼叫,即所有帧都具有最终大小的呼叫是最后一个。据我所知,没有办法知道最后一个是哪个电话。
我们习惯拥有一个' framesAreSet' flag(初始化为false)和一个检查,如果frame不为零(类似于self.view.frame.size.width != 0
)和' framesAreSet'是假的,它进去,转动旗帜并只计算一次。类似的东西:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
if (self.view.frame.size.width != 0 && !framesAreSet)
{
framesAreSet = true;
//Calculate frames here
}
}
这看起来不错,但实际上,检查self.view.frame.size.width != 0
之类的内容不可以保证确实设置了帧。 viewDidLayoutSubviews
之后被调用的事实表明某些帧未设置为最终状态。
拥有viewCompleteLayoutSubviews
会很棒。任何关于什么是实现“一次性”的最佳方式的想法。设置所有帧并且视图不可见时的帧计算?
(这可能是使用NSConstraints查看不的问题)
答案 0 :(得分:1)
该应用每次绘制只获得一个didLayoutSubviews
(截至该点,视图状态更改仅记录setNeedsLayout
)。从这个意义上讲,didLayoutSubviews
是您对didCompleteLayoutOfSubviews
的看法。绘制后,如果发生另一个视图状态更改,则布局再次不完整。
换句话说,didLayout调用的数量不依赖于子视图添加或帧更改的数量,它取决于绘制的数量(不要与运行循环混淆)。在绘制之前,如果设置了needsLayout标志,则无论视图层次结构重新排列多少,layoutSubviews和didLayoutSubviews都将被调用一次。
答案 1 :(得分:1)
您应该始终为视图当前所具有的维度重新布局。
您可以设置帧,然后旋转设备。你需要重新计算框架吗?当然,边界大小已经改变了!您正在使用framesAreSet
进行危险的假设。
如果性能确实对您很关键,那么您可能希望将计算框架缓存为某些字典,如果边界尺寸发生变化,则无效。
但是你肯定不会仅仅执行一次布局。
另一种方法是让视图控制器view
成为自定义类的实例并覆盖-layoutSubviews
。
答案 2 :(得分:0)
你可以使用dispatch once token(GCD)计算viewDidLayoutSubviews方法中的帧,如果帧被初始化,一旦这不会进入你的dispatchonce块。