NSHostingController/View不遵循SwiftUI内容尺寸的原因及解决方法
问题原因
- NSHostingController和NSHostingView在AppKit环境下默认会优先匹配父容器提供的尺寸,没有主动适配内部SwiftUI内容的固有尺寸。
- 宿主控件的内容拥抱优先级、抗压缩优先级默认低于父视图约束,即使SwiftUI内容计算出了合适尺寸,也会被宿主控件的拉伸行为覆盖,导致单独给SwiftUI加
fixedSize不生效。
修复方案
方案1:重写NSHostingController的尺寸属性
修改你的TestViewController代码即可:
class TestViewController: NSHostingController<TestView> { required init?(coder: NSCoder) { super.init(coder: coder, rootView: TestView()) view.needsLayout = true } // 绑定SwiftUI内容的计算尺寸作为固有尺寸 override var intrinsicContentSize: NSSize { rootView.sizeThatFits(in: CGSize( width: .greatestFiniteMagnitude, height: .greatestFiniteMagnitude )) } // 布局变化时自动刷新尺寸 override func viewDidLayout() { super.viewDidLayout() view.invalidateIntrinsicContentSize() } }
添加完成后给TestViewController的视图添加约束时,只需要设置位置约束,不需要设置宽高约束即可自适应内容尺寸。
方案2:如果使用NSHostingView,调整约束优先级
let hostingView = NSHostingView(rootView: TestView()) // 提高内容抗拉伸、抗压缩优先级,让内容尺寸优先生效 hostingView.setContentHuggingPriority(.required, for: .horizontal) hostingView.setContentHuggingPriority(.required, for: .vertical) hostingView.setContentCompressionResistancePriority(.required, for: .horizontal) hostingView.setContentCompressionResistancePriority(.required, for: .vertical) // 后续添加到父视图时仅设置位置约束即可
可选:SwiftUI侧补充限制
如果需要限制内容的最大宽高范围,可以在SwiftUI视图上添加frame约束:
public struct TestView: View { public var body: some View { VStack(spacing: 4) { ForEach(1..<5) { index in Text("Row: \(index)") Divider() } } // 示例:限制最大宽度300,高度自适应 .frame(maxWidth: 300, maxHeight: .infinity, alignment: .top) } }
内容的提问来源于stack exchange,提问作者user187676
相关产品推荐
相关产品推荐

