0

我不明白为什么SwiftUI NavigationLink'sisActive表现得好像它有自己的状态。即使我将一个常量传递给它,后退按钮也会在按下后覆盖绑定的值。

代码:


import Foundation
import SwiftUI

struct NavigationLinkPlayground: View {

    @State
    var active = true

    var body: some View {

        NavigationView {
            VStack {
                Text("Navigation Link playground")
                Button(action: { active.toggle() }) {
                    Text("Toggle")
                }

                Spacer()
                        .frame(height: 40)

                FixedNavigator(active: active)
            }
        }
    }

}

fileprivate struct FixedNavigator: View {

    var active: Bool = true

    var body: some View {
        return VStack {
            Text("Fixed navigator is active: \(active)" as String)

            NavigationLink(
                    destination: SecondScreen(),
                    // this is technically a constant!
                    isActive: Binding(
                            get: { active },
                            set: { newActive in print("User is setting to \(newActive), but we don't let them!") }
                    ),
                    label: { Text("Go to second screen") }
            )
        }
    }

}

fileprivate struct SecondScreen: View {

    var body: some View {
        Text("Nothing to see here")
    }

}


这是一个最小的可重现示例,我的实际意图是手动处理后退按钮按下。因此,当调用set内部时Binding,我希望能够决定何时实际进行。(所以就像基于一些验证或其他东西。)

而且我不明白发生了什么以及为什么后退按钮能够覆盖常量绑定。

4

1 回答 1

1

你的使用isActive是错误的。isActive接受一个绑定布尔值,每当您将该绑定布尔值设置为true时,导航链接就会被激活,您将被导航到目的地。
isActive 控制导航链接是否可点击/禁用。下面是一个正确使用的例子isActiveactivateNavigationLink您可以通过设置来手动触发导航到您的第二个视图true

编辑1:

在这个新的示例代码中,您也可以随意禁用和启用后退按钮:

struct ContentView: View {
    
    @State var activateNavigationLink = false
    
    var body: some View {
        NavigationView {
            VStack {
                // This isn't visible and should take 0 space from the screen!
                // Because its `label` is an `EmptyView`
                // It'll get programmatically triggered when you set `activateNavigationLink` to `true`.
                NavigationLink(
                    destination: SecondScreen(),
                    isActive: $activateNavigationLink,
                    label: EmptyView.init
                )
                
                Text("Fixed navigator is active: \(activateNavigationLink)" as String)
                
                Button("Go to second screen") {
                    activateNavigationLink = true
                }
            }
        }
    }
}

fileprivate struct SecondScreen: View {
    
    @State var backButtonActivated = false
    
    var body: some View {
        VStack {
            Text("Nothing to see here")
            
            Button("Back button is visible: \(backButtonActivated)" as String) {
                backButtonActivated.toggle()
            }
        }
        .navigationBarBackButtonHidden(!backButtonActivated)
    }
}
于 2021-04-13T07:49:13.530 回答