SwiftUI 模态演示仅在 navigationBarItems 中有效

Posted

技术标签:

【中文标题】SwiftUI 模态演示仅在 navigationBarItems 中有效【英文标题】:SwiftUI modal presentation works only once from navigationBarItems 【发布时间】:2020-03-02 08:55:20 【问题描述】:

当您从导航栏项目内的按钮显示模式时,这是 SwiftUI 中的一个错误。 在下面的代码中,按钮 1 按预期工作,但按钮 2 只工作一次:

struct DetailView: View 

    @Binding var isPresented: Bool
    @Environment (\.presentationMode) var presentationMode

    var body: some View 
        NavigationView 
            Text("OK")
            .navigationBarTitle("Details")
            .navigationBarItems(trailing: Button(action: 
                self.isPresented = false
                // or:
                // self.presentationMode.wrappedValue.dismiss()
            ) 
                Text("Done").bold()
            )
        
    


struct ContentView: View 

    @State var showSheetView = false

    var body: some View 
        NavigationView 
            Group 
                Text("Master")
                Button(action:  self.showSheetView.toggle() ) 
                    Text("Button 1")
                
            
            .navigationBarTitle("Main")
            .navigationBarItems(trailing: Button(action: 
                self.showSheetView.toggle()
            ) 
                Text("Button 2").bold()
            )
        .sheet(isPresented: $showSheetView) 
            DetailView(isPresented: self.$showSheetView)
        
    

这个bug是去年年中的,现在还在Xcode 11.3.1 + ios 13.3 Simulator和iOS 13.3.1 iPhone XS中。

这里有什么解决方法可以让按钮工作吗?

编辑:

    似乎是点击区域向下某处,可以点击下面的按钮以显示模式。

对此的临时解决方案是使用内联导航栏模式: .navigationBarTitle("Main", displayMode: .inline)

【问题讨论】:

一旦签入设备就可以工作了。 嗯,在设备上它第一次也可以正常工作,但是对于接下来的点击,您需要在按钮本身下方的某个地方非常绅士地按下(几乎长按),这是奇怪而不是预期的行为 【参考方案1】:

好吧,问题在于工作表关闭后导航栏按钮的布局错误(似乎约束被破坏)

在视图层级调试中清晰可见:

这是一个修复(当然是解决方法,但安全,因为即使问题得到修复,它也会继续工作)。这个想法不是与损坏的布局作斗争,而只是创建另一个按钮,因此布局引擎本身会删除旧的坏按钮并添加新的令人耳目一新的布局。这方面的工具是众所周知的 - 使用.id()

所以修改了代码:

struct ContentView: View 

    @State var showSheetView = false
    @State private var navigationButtonID = UUID()

    var body: some View 
        NavigationView 
            Group 
                Text("Master")
                Button(action:  self.showSheetView.toggle() ) 
                    Text("Button 1")
                
            
            .navigationBarTitle("Main")
            .navigationBarItems(trailing: Button(action: 
                self.showSheetView.toggle()
            ) 
                Text("Button 2").bold() // recommend .padding(.vertical) here
            
            .id(self.navigationButtonID)) // force new instance creation
        
        .sheet(isPresented: $showSheetView) 
            DetailView(isPresented: self.$showSheetView)
                .onDisappear 
                    // update button id after sheet got closed
                    self.navigationButtonID = UUID()
                
        
    

【讨论】:

Apple 仍未在 xCode 版本 11.5 (11E608c) 中解决此问题 在 Xcode 12.5 (12E262) 中仍然有这个问题 Xcode 13.0 beta (13A5154h) - 仍然看到这个问题。

以上是关于SwiftUI 模态演示仅在 navigationBarItems 中有效的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 模态演示在 iPad 模拟上搞砸了?

无法在 SwiftUI 中使用 ForEach 和 CoreData 将数据正确传递给模态演示

SwiftUI - 通过 ContextMenu 呈现模态

如何在 SwiftUI 中模态地推动下一个屏幕充满

以非模态方式呈现视图

SwiftUI:模态表隐藏 ProgressView