Home > Back-end >  Change state through function within same file but outside struct
Change state through function within same file but outside struct

Time:10-24

I have a loading screen that should navigate to the contentview once a few images have finished loading. I load the images using the first two functions and finally trigger navigation to content view. Navigation is triggered when a state variable activateNavigation turns true. The issue is I need to change state in a function outside the struct. I can't seem to figure out how to do this, you can see it in the final code snippet below.

LoadingScreen().onAppear(){
   getImages();
   convertImages();
   triggerNavigationToContentView();
}
struct LoadingScreen: View{
    @State var text = ""
    @State var activateNavigation = false
    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
    var body: some View{
        NavigationView{
            VStack{
                Text("Loading images \(text)")
                    .font(.system(size: 24)).bold()
                    .transition(.slide)
                    .onReceive(timer, perform: {(_) in
                        if self.text.count == 3 {
                            self.text = ""
                        } else {
                            self.text  = "."
                        }
                    })
                    .onAppear(){
                        self.text = "."
                    }
                NavigationLink(destination: ContentView(), isActive: $activateNavigation, label: { EmptyView() })
            }
            
        }
    }
}
triggerNavigationToContentView(){
    activateNavigation = true;
}

CodePudding user response:

You can create a Binding inline using the init(get:set:) initializer.

...

NavigationLink(
    destination: ContentView(),
    isActive: .init(
        get: { activateNavigation },
        set: { activateNavigation = $0 }
    ),
    label: { EmptyView() }
)

...

CodePudding user response:

If you inject the binding into your second View it should work fine.

NavigationLink(destination: ContentView($activateNavigation), isActive: $activateNavigation, label: { EmptyView() })
struct ContentView: View {
  @Binding var activateNavigation: Bool

  init(_ activateNavigation: Binding<Bool>) {
    self.activateNavigation = activateNavigation
  }
}

Bindings are persisted throughout view routes, so if you now set activateNavigation in ContentView it will update in LoadingScreen too (and vice versa).

You can use Bindings in initialisers for other structs too if you need to trigger the flow elsewhere. I don’t recommend global functions.

Note that using $activateNavigation implicitly converts the @State into an @Binding, no boilerplate needed.

  • Related