Search code examples
swiftuitimernavigationview

SwiftUI sharing timer through views in navigation view


I'm pretty new at SwiftUI. I would like to make an app that navigates through different views in a Navigation View and running a timer in background presenting the time on each of the views. The problem is when I navigate to a second level of navigation. When the timer is on, the app returns automatically to the previous navigation view. Here's is a screenshot video of what I mean: https://youtu.be/eXbK9jpluvk

Here is my code:

import SwiftUI

struct ContentView: View {

@State var timer = Timer.publish(every: 1,  on: .main, in: .common).autoconnect()
@State var seconds : Int = 0
@State var paused : Bool = true

var body: some View {
    
    
    VStack {
        Text("\(seconds)")
        Button(action: {
            paused.toggle()
        }) {
            Image(systemName: paused ? "play.fill" : "stop.fill")
        }
        NavigationLink(destination: FirstView( timerSeconds: $seconds, timerPaused: $paused)) {
            Text("Navigate 1")
        }.padding()
    }
    .onReceive(self.timer) { currentTime in
        if !paused {
            seconds = seconds + 1
            print(currentTime)
        }
    }
    .navigationViewStyle(.stack)
    
}

}

struct FirstView: View {

@Binding var timerSeconds : Int
@Binding var timerPaused : Bool

var body: some View {
    
        VStack {
            Text("First View")
            Text("\(timerSeconds)")
            Button(action: {
                timerPaused.toggle()
            }) {
                Image(systemName: timerPaused ? "play.fill" : "stop.fill")
            }
            NavigationLink(destination: SecondView(seconds: $timerSeconds)) {
                Text("Navigate 2")
            }
        }
    
}

}

struct SecondView: View {

@Binding var seconds : Int

var body: some View {
    Text("\(seconds)")
}

}

Any help will be welcome!! Thanks a lot


Solution

  • NavigationView can only push on one detail NavigationLink so to have more levels you need to set .isDetailLink(false) on the link. Alternatively, if you don't expect to run in landscape split view, you could set .navigationViewStyle(.stack) on the navigation.