systemLayoutSizeFitting returns 始终为零

systemLayoutSizeFitting returns zero always

基于 Apple 的 docsystemLayoutSizeFitting 应该在返回最佳尺寸时尊重 UIView 元素的当前约束。但是,每当我 运行 跟随代码时,我会得到 UIView.layoutFittingCompressedSize{0, 0}UIView.layoutFittingExpandedSizeSize 输入的 {1000, 1000}

let mainView = UIView(frame: CGRect(origin: .zero, size: CGSize(width: 375, height: 50)))
mainView.backgroundColor = .red
PlaygroundPage.current.liveView = mainView

let subview = UIView()
subview.backgroundColor = .yellow
mainView.addSubview(subview)
subview.snp.makeConstraints { make in
    make.width.equalToSuperview().dividedBy(3.0)
    make.left.top.bottom.equalToSuperview()
}
mainView.setNeedsLayout()
mainView.layoutIfNeeded()

subview.frame

subview.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)

我注意到,如果我将 width 约束更改为常量,那么我将从 systemLayoutSizeFitting 中获得有效值。试图理解为什么会发生这种行为,以及是否有可能从 systemLayoutSizeFittingSize(_ size: CGSize).

中获得正确的值

这方面的文档似乎相当缺乏。

看来 .systemLayoutSizeFitting 高度依赖于元素的 .intrinsicContentSize。对于 UIView,它没有固有的内容大小(除非您已覆盖它)。

因此,如果相关约束是另一个约束的 百分比 ,则 .systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) 将 return {0, 0}。我认为这是因为相关约束可能会更改(变为零),因此最小值实际上为零。

如果您将 .width 约束更改为常量(例如 mainView.frame.width * 0.3333),那么您将获得有效的尺寸值,因为恒定宽度约束变为固有宽度。

例如,如果您的子视图是 UILabel,该元素 具有固有大小,并且 .systemLayoutSizeFitting 应该 return您期望的尺寸值。

这是一个使用 UILabel 的示例,将演示:

import UIKit
import PlaygroundSupport

let mainView = UIView(frame: CGRect(origin: .zero, size: CGSize(width: 375, height: 50)))
mainView.backgroundColor = .red
PlaygroundPage.current.liveView = mainView

let v = UILabel()
v.text = "Testing"
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .green
mainView.addSubview(v)

NSLayoutConstraint.activate([
    v.widthAnchor.constraint(equalTo: mainView.widthAnchor, multiplier: 3.0 / 10.0),
    v.leftAnchor.constraint(equalTo: mainView.leftAnchor),
    v.topAnchor.constraint(equalTo: mainView.topAnchor),
    v.bottomAnchor.constraint(equalTo: mainView.bottomAnchor),
    ])

mainView.setNeedsLayout()
mainView.layoutIfNeeded()

v.frame

v.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)