提问者:小点点

`uiscrollview``bounds`在`viewDidExpeople`中与上一个`viewDidLayoutSubviews`不同


为了改进较小设备的UI,当uiscrollviewcontentsize.height大于其bounds.height时(我称之为溢出),我希望调整UI。

我的问题是:我发现视图出现在屏幕上后(在ViewDidAppear(:))的布局与上次出现在ViewDidLayoutSubViews()中的布局不同(可以多次调用)。 为了确定ScrollView是否溢出,我们需要知道ScrollView.boundsScrollView.ContentSize。 我认为这将在ViewDidLayoutSubViews()的最后一次调用中确定。

下面举例说明我的场景。 它正在运行一个内置在xib中的接口,其中还设置了scrollview。 注意,没有隐藏/显示视图来干扰布局值,只需运行。

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    printOverflow(type: #function)
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    printOverflow(type: #function)
}

private func printOverflow(type: String) {
    let isOverflowY = scrollView.contentSize.height > scrollView.bounds.height
    debugPrint("[Overflow] \(type) \(isOverflowY ? "Overflow" : "Fits")")
}

// After running prints:
// "[Overflow] viewDidLayoutSubviews() Fits"
// "[Overflow] viewDidAppear(_:) Overflow"

我的问题是:为什么不能在最后一个ViewDidLayoutSubviews()中获得子视图的最终布局?

我还尝试在ViewWillAppearch(:)中添加了一个View.LayoutifNeed(),实际上这激发了另一个ViewDidLayoutSubViews(),正如您所期望的,但是Bounds属性仍然与ViewDidAppearch(:)中的不同(尽管实际上现在打印的是“溢出”)


共1个答案

匿名用户

来自苹果的文档(斜体是我的):

函数viewDidLayoutSubviews()

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

因此,ViewDidLayoutSubViews()可以(也将)在自动布局完全配置子视图之前调用。 这也是我们看到ViewDidLayoutSubViews()在加载/显示过程中被多次调用的原因。

如果您像这样对UISCROLLView进行子类划分:

class MyScrollView: UIScrollView {

    override func layoutSubviews() {
        super.layoutSubviews()
        printOverflow(type: #function)
    }

    private func printOverflow(type: String) {
        let isOverflowY = contentSize.height > bounds.height
        debugPrint("MyScrollView {Content Size: \(contentSize.height) Bounds Height: \(bounds.height)} [Overflow] \(type) \(isOverflowY ? "Overflow" : "Fits")")
    }

}

你会发现你得到了正确的高度。

到底是为了“改善更小设备的UI”而尝试做些什么呢? 可能还有其他(更好的?) 选项。。。