I asked this question on StackOverflow - https://stackoverflow.com/questions/63104172/swiftui-navigationview-with-presentationmode-creates-bug-in-multilevel-navigatio also, but my interactions there have lead me to think this might be a SwiftUI bug, so I thought I'd ask here too.
I have an iOS 13.5 SwiftUI (macOS 10.15.6) app that requires the user to navigate two levels deep in a NavigationView hierarchy to play a game. The game is timed. I'd like to use custom back buttons in both levels, but if I do, the timer in the second level breaks in a strange way. If I give up on custom back buttons in the first level and use the system back button everything works. Here is a minimum app that replicates the problem:
class SimpleTimerManager: ObservableObject {
	@Published var elapsedSeconds: Double = 0.0
	private(set) var timer = Timer()
	
	func start() {
		print("timer started")
		timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) {_ in
			if (Int(self.elapsedSeconds * 100) % 100 == 0) { print ("\(self.elapsedSeconds)") }
			self.elapsedSeconds += 0.01
		}
	}
	
	func stop() {
		timer.invalidate()
		elapsedSeconds = 0.0
		print("timer stopped")
	}
}
struct ContentView: View {
	var body: some View {
		NavigationView {
			NavigationLink(destination: CountDownIntervalPassThroughView()) {
				Text("Start the timer!")
			}
		}
		.navigationViewStyle(StackNavigationViewStyle())
	}
}
struct CountDownIntervalPassThroughView: View {
	@Environment(\.presentationMode) var mode: Binding<PresentationMode>
	var body: some View {
		VStack {
			NavigationLink(destination: CountDownIntervalView()) {
				Text("One more click...")
			}
			Button(action: {
				self.mode.wrappedValue.dismiss()
				print("Going back from CountDownIntervalPassThroughView")
			}) {
				Text("Go back!")
			}
		}
		.navigationBarBackButtonHidden(true)
	}
}
struct CountDownIntervalView: View {
	@ObservedObject var timerManager = SimpleTimerManager()
	@Environment(\.presentationMode) var mode: Binding<PresentationMode>
	var interval: Double { 10.0 - self.timerManager.elapsedSeconds }
		
	var body: some View {
		VStack {
			Text("Time remaining: \(String(format: "%.2f", interval))")
				.onReceive(timerManager.$elapsedSeconds) { _ in
					print("\(self.interval)")
					if self.interval <= 0 {
						print("timer auto stop")
						self.timerManager.stop()
						self.mode.wrappedValue.dismiss()
					}
			}
			Button(action: {
				print("timer manual stop")
				self.timerManager.stop()
				self.mode.wrappedValue.dismiss()
			}) {
				Text("Quit early!")
			}
		}
		.onAppear(perform: {
			self.timerManager.start()
		})
		.navigationBarBackButtonHidden(true)
	}
}
Poking at this some more, I see two strange behaviors. If I don't use a pass through, everything works for manual clicking. But if I let the timer expire and create a pop back, when I try to restart it, the view immediately pops, but the timer keeps running. If I do use a pass through, the timer starts when I navigate two levels down, but the view doesn't update. I wonder if this is a bug in how SwiftUI is handling the onAppear and mode.dismiss methods.