试图解决我现在有一段时间的问题
背景
让我们假设我尝试计算一个完全适合UIImageView的UIImage,它在故事板中配置了约束。
imageView的内容不应该填充/方面适合...但完全适合框架。 因此我的viewController中有一个方法
- (UIImage *)calculatedImageForRect:(CGRect)imageRect
问题
我想确保,只要视图变得可见,imageView就已包含正确的图像,因此在简单的推送过渡期间也是如此。 另外,我不想多次生成UIImage,因为它相对昂贵。
对于像iPhone6 plus这样具有不同屏幕分辨率的设备
,这一点尤其有趣显然,在viewDidLoad
时帧数设置不正确。此时,帧被设置为故事板的预览 - 例如用于表示IPhone5分辨率的设置。 viewWillAppear
也是如此。
这里框架将是例如是(10,10,300,100)< - 让我们称之为错误的框架
在viewDidAppear
帧正确(10,10,394,100)= 正确帧< - 而不是320点宽度,iPhone6Plus有414点。然而,这里为时已晚,因为视图已经可见并且设置图像会导致闪烁(空图像>新生成的图像)。
我知道使用宽度的正确时间是viewDidLayoutSubviews
,首先使用错误帧至少调用一次,然后使用进行一次调用正确帧。
但正如我所说,我不想多次生成图像,所以这就是困境:
如何在可见之前确定右框架?
当然,我可以通过使用尾随&分辨率从[UIScreen mainScreen]
分辨率计算出正确的帧。 UIImageView的主要限制,但它感觉很脏。
答案 0 :(得分:9)
您无法使用viewDidLayoutSubviews
的原因是,正如您所说,可能会多次调用它。 layoutSubviews
也是如此。
这是为什么?一个原因是因为基于约束的布局是一个迭代过程,可能涉及多次通过。例如,假设我强制视图V的布局,其在其视图层次结构中包含子视图W,其包含子视图X.X的布局的第一个自动布局计算可以改变约束,然后需要重新计算W然后需要重新计算X.这基本上不同于具有自动调整大小掩码的布局,它是自上而下的,因此外部视图总是指示其子视图的布局。
然而,我相信(但并非100%肯定),如果所有布局代码都正确实现,那么这些多个布局通道都应该在运行循环的一圈内发生。也就是说,当您通过调用layoutIfNeeded
来强制在V上布局来启动此过程时,您可以确保所有自动布局布局传递W和X已完成,一次{{1返回。不需要布局"或者"需要更新约束"标志将被留下脏,等待运行循环的下一轮完成工作。
这可能指向您的解决方案。如果强制层次结构中的顶级视图的早期布局(例如正在转换到的视图控制器的根视图),那么当该布局传递完成时,layoutIfNeeded
将具有正确的框架,并且您可以使用该帧生成图像。
基本上,你不是在最后一刻做布局,而是强迫它提前完成。然后,您可以知道它何时完成,因为您已启动它,并且可以通过等待UIImageView
退出来查看该过程的结束。然后你可以观察你关心的结果值。