You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在macOS的NavigationStack中弹出sheet崩溃,iPadOS无此问题

macOS下NavigationStack推送视图弹出Sheet崩溃问题

问题描述

在macOS系统中,从NavigationStack的推送视图里触发弹出sheet时程序直接崩溃,但相同代码在iPadOS上运行完全正常。

复现代码

struct ContentView: View {
    var body: some View {
        NavigationSplitView
        {
            List
            {
                Text("Foo")
                Text("Bar")
            }
            .navigationSplitViewColumnWidth(min: 200, ideal: 200)
        }
        detail:
        {
            NavigationStack
            {
                Text("The Detail")
                    .navigationTitle("Detail")
                    .toolbar
                    {
                        ToolbarItemGroup
                        {
                            NavigationLink(value: "New thing")
                            {
                                Label("New thing", systemImage: "plus")
                            }
                        }
                    }
                    .navigationDestination(for: String.self)
                    { _ in
                        AddView()
                    }
            }
        }
    }
}

struct AddView : View
{
    var body: some View
    {
        Text("new thing editor")
            .navigationTitle("New Thing")
            .toolbar
            {
                ToolbarItemGroup
                {
                    Button(action: { self.isPresentingSearch = true })
                    {
                        Label("Search Thing", systemImage: "magnifyingglass")
                    }
                }
            }
            .sheet(isPresented: self.$isPresentingSearch)
            {
                Text("Search Thing UI")
            }
    }
    
    @State private var isPresentingSearch = false
}

错误日志

点击放大镜按钮将isPresentingSearch设为true时,控制台输出以下错误日志:

2023-02-14 19:09:55.539599-0800 TestSheet[34435:770832] [General] The window has been marked as needing another Update Constraints in Window pass, but it has already had more Update Constraints in Window passes than there are views in the window. 
<_TtC7SwiftUIP33_00AAB847C3060B4FF7A299E87C10010C23SheetPresentationWindow: 0x15610d0e0> 0x5c3 (1475) {{0, 0}, {97, 44}} en Future marking as needing Update Constraints in Window might be ignored.
2023-02-14 19:09:55.546262-0800 TestSheet[34435:770832] [General] The window has been marked as needing another Update Constraints in Window pass, but it has already had more Update Constraints in Window passes than there are views in the window. 
<_TtC7SwiftUIP33_00AAB847C3060B4FF7A299E87C10010C23SheetPresentationWindow: 0x15610d0e0> 0x5c3 (1475) {{0, 0}, {97, 44}} en
2023-02-14 19:09:55.551251-0800 TestSheet[34435:770832] [General] (
    0   CoreFoundation                      0x00000001a49f83e8 __exceptionPreprocess + 176
    1   libobjc.A.dylib                     0x00000001a4542ea8 objc_exception_throw + 60
    2   CoreFoundation                      0x00000001a49f828c +[NSException exceptionWithName:reason:userInfo:] + 0
    3   AppKit                              0x00000001a7c337a4 -[NSWindow(NSDisplayCycle) _postWindowNeedsUpdateConstraintsUnlessPostingDisabled] + 1844
    4   AppKit                              0x00000001a7c1d790 -[NSView _informContainerThatSubviewsNeedUpdateConstraints] + 64
    5   AppKit                              0x00000001a7c1d714 -[NSView setNeedsUpdateConstraints:] + 460
    6   SwiftUI                             0x00000001cb7944c8 OUTLINED_FUNCTION_19 + 254512
    7   SwiftUI                             0x00000001cb764df4 OUTLINED_FUNCTION_19 + 60252
.
.
.

解决方案

这是macOS SwiftUI的已知布局约束bug,解决方法是将sheet的弹出逻辑从推送视图(AddView)转移到根视图层级,通过绑定状态控制sheet显示:

调整后的代码示例:

struct ContentView: View {
    @State private var isPresentingSearch = false
    
    var body: some View {
        NavigationSplitView
        {
            List
            {
                Text("Foo")
                Text("Bar")
            }
            .navigationSplitViewColumnWidth(min: 200, ideal: 200)
        }
        detail:
        {
            NavigationStack
            {
                Text("The Detail")
                    .navigationTitle("Detail")
                    .toolbar
                    {
                        ToolbarItemGroup
                        {
                            NavigationLink(value: "New thing")
                            {
                                Label("New thing", systemImage: "plus")
                            }
                        }
                    }
                    .navigationDestination(for: String.self)
                    { _ in
                        AddView(isPresentingSearch: $isPresentingSearch)
                    }
            }
        }
        .sheet(isPresented: $isPresentingSearch) {
            Text("Search Thing UI")
        }
    }
}

struct AddView : View {
    @Binding var isPresentingSearch: Bool
    
    var body: some View {
        Text("new thing editor")
            .navigationTitle("New Thing")
            .toolbar
            {
                ToolbarItemGroup
                {
                    Button(action: { isPresentingSearch = true })
                    {
                        Label("Search Thing", systemImage: "magnifyingglass")
                    }
                }
            }
    }
}

核心思路是避免在NavigationStack的推送视图内部直接附加sheet,而是将sheet绑定到更上层的视图(如NavigationSplitView),以此规避macOS上的布局约束冲突问题。

内容的提问来源于stack exchange,提问作者Rick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 20:15:51