SwiftUI/AppKit:如何让 NSHostingView 包裹 VStack 以填充其整个父级的高度,而不是拥抱堆栈

问题描述 投票:0回答:1

我有一个 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 内容的空间来“解决”问题。任何想法表示赞赏。

swift macos swiftui appkit
1个回答
0
投票

好吧,到今天结束时我已经弄清楚了。如果您的目标是 macOS 13 或更高版本,则可以将

sizingOptions
NSHostingView
属性设置为
[.minSize
],这只会查看 SwiftUI 大小来确定最小大小,而不是固有大小或最大大小。

但是,我的目标是 macOS 12,但我能够找到等效的解决方案,即子类化

NSHostingView
并重写
intrinsicContentSize
属性,如下所示:

    override var intrinsicContentSize: NSSize {
        var size = super.intrinsicContentSize
        size.height = NSView.noIntrinsicMetric
        return size
    }
© www.soinside.com 2019 - 2024. All rights reserved.