SwiftUI:不推荐使用 NavigationDestinationLink

SwiftUI: NavigationDestinationLink deprecated

今天早上安装 Xcode 11 beta 5 后,我注意到 NavigationDestinationLink 已被弃用,取而代之的是 NavigationLink

此外,这就是 Apple 在发行说明中所说的:

NavigationDestinationLink and DynamicNavigationDestinationLink are deprecated; their functionality is now included in NavigationLink. (50630794)

我使用 NavigationDestinationLink 的方式是通过 self.link.presented?.value = true 以编程方式将新视图推送到堆栈中。 NavigationLink 中似乎没有该功能。

有人知道吗? 我宁愿不再使用 NavigationDestinationLink,因为它已被弃用...

谢谢!

更新: 实际上,NavigationDestinationLink 方式不再有效,所以我想我们无法再以编程方式推送?

更新 2:

NavigationLink(destination: CustomView(), isActive: $isActive) {
    return Text("")
}

这行得通,但是当你将 isActive 传递给 true 时,任何状态更新都会触发此代码并一遍又一遍地推送...另外,如果你将它传回 false,它将弹出视图。 不仅更新,如果您将 isActive 设置为 true,它会推送视图(好),如果我们按下后退按钮,它会返回然后立即再次推送,因为它仍然是正确的。 玩 onAppear 是我的希望,但回到它时它不会被调用...... 我不确定我们应该如何使用它。

NavigationLink(destination:isActive) 待了一段时间后,我比原来的 NavigationDestinationLink 更喜欢它。旧的视图有点混乱,而新的方法看起来更优雅。一旦我弄清楚如何在没有动画的情况下进行推送,它将使应用程序启动时的状态恢复变得非常容易。

但是有一个问题,一个又大又丑的错误。 :-(

以编程方式推送视图工作正常,以编程方式弹出它也可以。当我们在推送视图中使用 BACK 按钮时,问题就开始了,它每隔一段时间就会表现得很奇怪。第一次弹出视图时,视图会立即弹出并再次推送。第二次它工作正常。然后第三次从头再来

我创建了一个错误报告 (number here)。我建议你也这样做并参考我的电话号码,以帮助 Apple 将它们组合在一起并引起更多关注。

我设计了一个解决方法,基本上包括用我们自己的替换默认的后退按钮:

class Model: ObservableObject {
    @Published var pushed = false
}

struct ContentView: View {
    @EnvironmentObject var model: Model

    var body: some View {
        NavigationView {
            VStack {
                Button("Push") {
                    // view pushed programmatically
                    self.model.pushed = true
                }

                NavigationLink(destination: DetailView(), isActive: $model.pushed) { EmptyView() }
            }
        }
    }
}

struct DetailView: View {
    @EnvironmentObject var model: Model

    var body: some View {
        Button("Bring me Back (programatically)") {
            // view popped programmatically
            self.model.pushed = false
        }
        // workaround
        .navigationBarBackButtonHidden(true) // not needed, but just in case
        .navigationBarItems(leading: MyBackButton(label: "Back!") {
            self.model.pushed = false
        })
    }
}

struct MyBackButton: View {
    let label: String
    let closure: () -> ()

    var body: some View {
        Button(action: { self.closure() }) {
            HStack {
                Image(systemName: "chevron.left")
                Text(label)
            }
        }
    }
}

您也可以使用 NavigationLink(目的地:标签:选择)

NavigationLink(destination: MyModal(), tag: 1, selection: $tag) {
    EmptyView()
}

因此您可以通过编程方式将标记设置为 1 以推送 MyModal。这种方法与使用 Bool 绑定变量的方法具有相同的行为,因此当您第一次弹出时它会立即推送视图,希望他们会在下一个测试版中修复它。

与 DynamicNavigationDestinationLink 相比,我看到的这种方法的唯一缺点是您需要为 NavigationLink 提供视图,即使您不需要视图也是如此。希望他们能找到一种更简洁的方法来让我们以编程方式进行推送。

要在不将后退按钮替换为自定义按钮的情况下改进解决方法,您可以使用上面的代码:

NavigationLink(destination: Test().onAppear(perform: {
    self.editPushed = nil
}), tag: 1, selection: self.$editPushed) {
    Button(action: {
        self.editPushed = 1
    }) {
        Image(systemName: "plus.app.fill")
            .font(.title)
    }
}

onAppear 块将清除选择值以防止显示两次详细视图

解决方案是为详细视图创建自定义后退按钮并手动弹出详细视图。

.navigationBarItems(leading:
                Button(action: {
                    self.showDetail = false
                }) {
                    Image(systemName: "chevron.left").foregroundColor(.red)
                        .font(.system(size: 24, weight: .semibold))
                    Text("Back").foregroundColor(.red)
                    .font(.system(size: 19))
                }
            )