在Autolayout完成时是否会触发iOS方法?

时间:2014-05-09 01:32:02

标签: ios autolayout viewdidload

我有一个iOS应用程序,我需要知道新视图何时在屏幕上完全可见;也就是说,当Autolayout完成计算并且视图已完成绘制时。

在视图完全可见之前,ViewDidAppear似乎很好。如果我关闭Autolayout,那么时间似乎与人类感知一致,但我需要在这个项目中使用Autolayout(所以这不是一个解决方案......只是一个测试)。

当Autolayout完成计算时,是否有任何触发方法?或者视图实际可见时触发的另一种方法(因为ViewDidAppear不适用于此)?

谢谢!

6 个答案:

答案 0 :(得分:15)

以下内容可用于避免多次通话:

- (void) didFinishAutoLayout {

    // Do some stuff here.    

    NSLog(@"didFinishAutoLayout");
}

- (void) viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];


    [NSObject cancelPreviousPerformRequestsWithTarget:self
                                 selector:@selector(didFinishAutoLayout)
                                           object:nil];
    [self performSelector:@selector(didFinishAutoLayout) withObject:nil
               afterDelay:0];
}

答案 1 :(得分:4)

我正在使用viewDidLayoutSubviews。 Apple的文档说,"被调用以通知视图控制器它的视图刚刚布局了它的子视图。"

答案 2 :(得分:0)

在我的案例中它的作用是在更改约束值后的请求布局:

a1         a2     b1         b2     c1         c2     d1         d2
5/02/2016  100    5/02/2016  96     5/02/2016  100    5/02/2016  (NULL)
5/09/2016  100    5/09/2016  100    5/09/2016  100    5/09/2016  (NULL)
5/16/2016  66     5/16/2016  100    5/16/2016  100    5/16/2016  100
5/23/2016  88     5/23/2016  80     5/23/2016  100    5/23/2016  100
5/30/2016  100    5/30/2016  100    5/30/2016  100    5/30/2016  (NULL)

e1         e2     f1         f2     g1         g2     h1         h2
5/02/2016  100    5/02/2016  100    5/02/2016  100    5/02/2016  98
5/09/2016  100    5/09/2016  5      5/09/2016  100    5/09/2016  83
5/16/2016  100    5/16/2016  (NULL) 5/16/2016  (NULL) 5/16/2016  80
5/23/2016  20     5/23/2016  66     5/23/2016  (NULL) 5/23/2016  63
5/30/2016  100    5/30/2016  100    5/30/2016  (NULL) 5/30/2016  100

稍后覆盖layoutSubviews方法:

    self.cnsTableviewHeight.constant = 50;
    [self layoutIfNeeded];

您也可以调用setNeedsLayout而不是layoutIfNeeded

答案 3 :(得分:0)

我认为实现"25";是正确的方法,但我使用动画只是在同一方法中编写完成回调。

viewDidLayoutSubviews

答案 4 :(得分:0)

您可能不仅会遇到UIViewControllers的问题,还会遇到UIViews的问题。如果您有一个子视图,并且想知道AutoLayout是否已更新其边界,则这是Swift 5的实现,

var viewBounds: CGFloat = 0.0
var autoLayoutHasCompleted: Bool = false

override func awakeFromNib() {
    super.awakeFromNib()

    // someSubView is the name of a view you want to check has changed
    viewBounds = someSubView.bounds.width 
}    

override func layoutSubviews() {
    if viewBounds != someSubView.bounds.width && !autoLayoutHasCompleted {
        // Place your code here
        autoLayoutHasCompleted = true
    }
}

答案 5 :(得分:0)

如果您观看了2018年的WWDC关于“高性能自动版式”的信息,您将知道此问题的答案。

从技术上讲,当自动布局完成视图的布局时,不会调用任何此类API方法。但是,当自动布局完成计算后,将调用视图的setBounds和setCenter,以便获取视图的大小和位置。

此后,将调用视图的layoutSubviews。因此,可以在某种程度上将layoutSubviews视为自动布局完成计算后触发的方法。

关于查看控制器的viewDidLayoutSubviews,这有点复杂。该文档说:

当视图控制器的视图的边界改变时,视图将调整其子视图的位置,然后系统调用此方法。但是,调用此方法并不表示该视图的子视图的各个布局已调整。每个子视图负责调整其自己的布局。

因此,当在视图控制器上调用viewDidLayoutSubviews时,只能确保正确布置视图控制器的view的第一级子视图。