SwiftUI Sheets:与 navigationBarItems 不一致的工作表行为

d00*_*m3n 5 ios swift swiftui

Xcode:版本 11.3 (11C29)
目标:运行 iOS 13.3 的模拟器

在使用工作表和 SwiftUI 时,我遇到了难以诊断的不一致行为。当我:
*NavigationView本身使用一个按钮时,我可以始终如一地调用工作表并关闭它
* 使用NavigationView(即navigationBarItems)栏中的按钮,行为不一致:有时它切换没有问题,有时它会“锁定up”并且在再次运行之前大约 10 秒没有响应。在界面中四处滑动并执行其他操作似乎有助于“重置”功能。

最小可重现示例:

import SwiftUI

struct ContentView: View {
    @State var isModalShowing = false

    var body: some View {
        NavigationView {
            VStack {
                List {
                    ForEach(1..<5) { number in
                        Text(String(number))
                    }
                }
                Button("First Modal Button") {
                    self.isModalShowing = true
                }
            }
            .navigationBarItems(leading:
                Button("Second Modal Button") {
                    self.isModalShowing = true
            })
        }
        .sheet(isPresented: $isModalShowing) {
            TestView(isPresented: self.$isModalShowing)
        }
    }
}

struct TestView: View {
    @Binding var isPresented: Bool
    var body: some View {
        VStack {
            Text("Hello SwiftUI!")
            Button("Dismiss") {
                self.isPresented = false
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Run Code Online (Sandbox Code Playgroud)

注意:
*First modal button持续
按下 *Second modal button第一次关闭模态后按下工作不一致(尝试连续使用此按钮约 5-10 次,它应该会锁定,但很难预测何时会锁定)

已经有一些关于这个的StackOverflow 问题/答案,但到目前为止没有一个对我有用,他们似乎在谈论 Xcode Betas,而我处于稳定状态(希望 11.3 是稳定的)。传递状态(@Bindingvs @Environment)的不同方式没有帮助。在.sheet被调用的地方移动也没有改变任何东西。我认为这也与List和/或有关,ForEach但我是 Swift 的新手,不确定如何进一步调试。

nay*_*yem 5

我相信这是一个错误。虽然我的回答不会解决这个问题,但可以给你选择考虑。

出于好奇,我对视图层次结构进行了一些调试。使用当前设置,最初导航栏按钮停留在此处(突出显示为蓝色):

在此处输入图片说明

然后您出示表格并相应地取消表格。解散后,导航栏按钮的位置不太对。看:

在此处输入图片说明

Text按钮停留在正确的位置,但栏按钮是从那里应该是流离失所。

但是,如果您使用NavigationLink而不是.sheet演示文稿,则不会发生这种位移。

嗯,这个问题普遍存在于导航栏标题的large选项中TitleDisplayMode,并且它是相当长一段时间的默认设置。但如果使用该inline选项,则问题不存在。请参阅,使用该inline选项,在工作表关闭之前和之后,导航栏按钮保持在同一位置:

在此处输入图片说明


这意味着,您现在有两个选择要考虑:

  1. 使用NavigationLink而不是工作表演示。您可以通过将以下代码放在最外层View(在您的情况下是VStack)来完成此操作:

    NavigationLink(destination: TestView(), isActive: self.$isModalShowing) {
        EmptyView()
        // no need to provide any other view as it will be triggered by the action
        // of navigation bar button item which already provides its own view
    }
    
    Run Code Online (Sandbox Code Playgroud)

注意:此NavigationLink选项未在Xcode 11.3或更高版本上进行测试,因为导航链接在此版本中似乎行为不当。但按预期工作到Xcode 11.2.1。有关SwiftUI 无法使用 navigationLink 来回导航的更多信息

  1. 使用inline导航栏的选项TitleDisplayMode作为:

    .navigationBarTitle(Text("Home"), displayMode: .inline)
    // you can get rid of the title "Home" with empty "" string though
    
    Run Code Online (Sandbox Code Playgroud)