2

我有一个高度可变的单元格,在 Interface Builder ( )UITableView中使用自动布局进行布局。rowHeight = UITableViewAutomaticDimension当用户旋转设备时,我会在单元格内执行一些手动布局更改,这些更改会影响intrinsicContentSize单元格的子视图之一。由于这些更改取决于该特定子视图的初始框架,因此我只能在布局引擎解决约束并将正确的框架应用于新(旋转)布局的所有子视图后应用这些更改。这发生在layoutSubviews()方法内部。因此,要应用我的手动更改,我会覆盖该方法并首先调用超级实现。

override func layoutSubviews() {
    // Call `super` implementation to let the layout engine do its job 
    // and apply the new frames to subviews after resolving constraints.
    super.layoutSubviews() 

    //  Apply manual layout changes here
} 

现在的问题是我的手动布局更改可能还会更改单元格的高度。因此,我需要一种方法来通知表格视图,在(自动)高度计算返回之前,此单元格需要第二次布局传递。(否则表格视图将只使用它在手动布局更改之前计算的行高。)

通常,您通过setNeedsLayout()调用需要另一个布局传递的视图来使布局无效来做到这一点。但是,我不能从layoutSubviews()方法内部执行此操作,因为它会导致布局传递的无限循环并使应用程序崩溃。

所以我试图找出一种方法,如果布局在这个特定的调用中发生了变化,layoutSubviews()并提出了这种方法:

override func layoutSubviews() {

    // Get old image view size before layout pass
    let previousImageSize = imageView.frame.size

    // Run a layout pass
    super.layoutSubviews()

    // Get the new image view size
    let newImageSize = imageView.frame.size

    // Only trigger a new layout pass if the size changed
    if newImageSize != previousImageSize {

        //  Apply manual layout changes here

        // Trigger another layout pass
        setNeedsLayout()
    }

}

(在本例中,这imageView是我的布局所依赖的单元格的子视图。)

运行这段代码时,我意识到if分支内的代码永远不会执行,即方法imageView内的大小永远不会改变layoutSubviews()。但它确实改变了——只是在不同的时间。

这与我对自动布局的理解不一致:

视图始终负责布置其子视图,即适当地设置它们的框架,这是在layoutSubviews().


所以这是我的问题:

  1. 为什么系统会从方法外部更改图像视图的大小layoutSubviews()

更重要的是:

  1. 在计算单元格的行高时,如何让表格视图运行第二次布局传递?
4

0 回答 0