我有一个 AppKit 应用程序,我想在其中使用 NSHostingView 嵌入 SwiftUI 视图。 SwiftUI 视图基于 VStack,如下所示:
struct IPReportView: View {
//This is rather long, but contains some lazy grid views that result in an overall view
//with a fixed width and height.
}
struct IPReportDetailView: View {
@Binding var report: IPReportDocument?
var body: some View {
if let selectedReport = report {
VStack(spacing: 20.0) {
Text(selectedReport.title)
.font(.headline)
IPReportView(reportDocument: selectedReport)
Spacer()
}
} else {
IPEmptyMessageView(header: "No report selected")
}
}
}
//Eventually there'll be a Split View but I just need to get the basics working first
struct IPReportListSplitView: View {
@ObservedObject var reportListViewModel: IPReportListViewModel
@State var selectedReport: IPReportDocument?
var body: some View {
IPReportDetailView(report: $selectedReport)
}
}
托管视图的设置如下所示:
//BWViewController is an NSViewController subclass. The calling code inserts
//IPReportListViewController's view with constraints to pin its sides to all four
//sides of its superview
class IPReportListViewController: BWViewController {
lazy var reportListViewModel: IPReportListViewModel = IPReportListViewModel(reports: IPReportDocument.allStoredReports())
override func loadView() {
let reportListMainView = IPReportListSplitView(reportListViewModel: self.reportListViewModel, selectedReport: self.reportListViewModel.reports.first)
let hostingView = NSHostingView(rootView: reportListMainView)
hostingView.translatesAutoresizingMaskIntoConstraints = false
hostingView.layer?.borderWidth = 1.0
hostingView.layer?.borderColor = NSColor.green.cgColor
self.view = hostingView
}
}
当我运行这个时,我得到的窗口看起来像这样。请注意绿色边框表示 NSHostingView 的边界。我想要实现的目标是让 NSHostingView 占据其超级视图的整个边界,并使报告视图与 NSHostingView 的顶部对齐。
我想找到的是某种方法让 IPReportDetailView 声明它需要 NSHostingView 提供的高度,而不是让 NSHostingView 缩小其高度以匹配 IPReportDetailView 的内在内容大小。让堆栈占用额外空间的正常堆栈是添加一个 Spacer(),我在这里已经完成了,但在托管视图的上下文中似乎没有执行任何操作。我还尝试在各个地方附加 .frame(maxHeight: .infinity) ,但没有效果。
我知道 NSHostingView 在其他情况下会占据整个内容区域,例如如果我将
report
绑定设置为 nil,它会显示 IPEmptyMessageView,它基本上是一个带有文本覆盖的 Color(.clear),它占据了整个内容区域。最终托管的 SwiftUI 视图将是 HSplitView,左侧是 SwiftUI 报告列表,右侧是报告详细信息,因此我不想通过在 NSHostingView 周围添加 AppKit 内容的空间来“解决”问题。任何想法表示赞赏。
好吧,到今天结束时我已经弄清楚了。如果您的目标是 macOS 13 或更高版本,则可以将
sizingOptions
的 NSHostingView
属性设置为 [.minSize
],这只会查看 SwiftUI 大小来确定最小大小,而不是固有大小或最大大小。
但是,我的目标是 macOS 12,但我能够找到等效的解决方案,即子类化
NSHostingView
并重写 intrinsicContentSize
属性,如下所示:
override var intrinsicContentSize: NSSize {
var size = super.intrinsicContentSize
size.height = NSView.noIntrinsicMetric
return size
}