简体   繁体   中英

SwiftUI navigate if ObservedObject property changes

I can't for the life of me figure out how to only navigate if a property from my ObservedObject changes to meet a condition. ie when my state changes to some condition, navigate to the next screen.

I've used the tag and selection initializer on the NavigationLink but it selection requires a Binding , and I can't derive a Binding from the properties on my ObservedObject without using the .constant() initializer on Binding which is only an immutable value.

@ObservedObject var store: Store<AppState, AppValue>

NavigationLink(
   destination: SecondView(),
   tag: true,
   selection: store.shouldNavigate // Can't do this because I need a binding
)

How else are people implementing buttons that only navigate if a condition in their state is met? I'm trying to avoid using the @State because I want the navigation to depend on my app state not on a local state that I'm toggling based on some business logic

public final class Store<Value, Action>: ObservableObject {
    @Published public private(set) var value: Value
}

UPDATE:

So it looks like I should be able to create a binding but since store.value gives me Binding<Value> I get an error: Generic parameter Subject cannot be inferred .

just remove private(set) in your model, NavigationLink will set shouldNavigate to false after navigation is completed, so it should not be private(set)

public final class Store<Value, Action>: ObservableObject {
    @Published public var value: Value
}

I show you an important intermediate solution before generics. I think the key here is that selection binding requires optional binding. That's most hassles coming from.

            enum AppState: String{
        case none = "none"
        case red = "red"
        case blue = "blue"
        case green = "green"
        case purple = "purple"
    }


    enum AppValue: String{
        case none
    }

    public final class Store<V, A>: ObservableObject {
        @Published  var value: AppState? = AppState.none
       public var link :Color = Color.white
        init(value: AppState = .none,  link : Color = Color.white){
            self.link = link
            self.value = value
        }
    }

     struct TestView: View {
        @ObservedObject var store: Store<AppState?, AppValue>

        var viewStates: [Store<AppState?,AppValue>] =
            [Store(value: .red, link: Color.red),
             Store(value: .blue, link: Color.blue) ,
             Store(value: .green, link: Color.green),
             Store(value: .purple, link: Color.purple)  ]

    var body: some View {
    NavigationView{
        VStack{
            ForEach(viewStates, id: \.value){ s in
                Group{
                NavigationLink(destination: s.link, tag: s.value!, selection: self.$store.value ){EmptyView()}
                    Button( s.value!.rawValue, action: {
                    self.store.value = s.value!})
                }}
        }
        }
    }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM