skip to Main Content

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;
}

2

Answers


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

    ...
    
    NavigationLink(
        destination: ContentView(),
        isActive: .init(
            get: { activateNavigation },
            set: { activateNavigation = $0 }
        ),
        label: { EmptyView() }
    )
    
    ...
    
    Login or Signup to reply.
  2. 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
      ...
    }
    

    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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search