在macOS的NavigationStack中弹出sheet崩溃,iPadOS无此问题
问题描述
在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
相关产品推荐
相关产品推荐

