On iOS 16 (16.4 specifically) and not iOS 17, I am running into an issue where navigationPath in MyNavigationViewModel is cleared when my app is backgrounded. I seemingly couldn't find much discussion around this happening. I'm hoping there is a work around and this is not intended, as the larger project I am working on depends on the state of navigationPath persisting despite being backgrounded.
Note: Since I am working on a larger project, so I'm trying to mimic it's structure, which is why I am doing things like passing my view model as an environment object, and having a button in the side bar to push the initial view on to the navigation destination.
To reproduce and observe the issue using the sample code below:
Swipe from the left edge of the screen to open the side bar (not sure why applying the .balanced style is not having the sidebar displace the detail view, but that's a separate issue I'm not concerned about...)
Click the button "Present Detail View"
Background the app
Wait some time (you will be able to see the print statement in the didSet print out a count of 0 for navigationPath)
Reopen the app
Observe the Base detail view is displayed, as opposed to the view that was pushed by pressing the side bar button. The navigation path was cleared.
Any advice on how to deal with this issue?
public class MyNavigationViewModel: ObservableObject {
@Published var navigationPath: [MyType] = [] {
didSet {
print("Count: \(self.navigationPath.count)")
}
}
}
public struct MyType: Hashable {
public var string: String
}
public struct MyDestination: View {
@EnvironmentObject var viewModel: MyNavigationViewModel
var text: String
let onBackPressed: ()->()
let onNextPressed: ()->()
public var body: some View {
VStack {
HStack {
Button(action: { self.onBackPressed() }, label: {Text("Back")})
Button(action: { self.onNextPressed() }, label: {Text("Next")})
}
Text("String: \(self.text).")
}
}
}
@available(iOS 16.0, *)
public struct MyNavigationView: View {
@EnvironmentObject var viewModel: MyNavigationViewModel
public var body: some View {
NavigationSplitView(
sidebar: {
VStack {
Button(
action: {
self.$viewModel.navigationPath.wrappedValue.append(MyType(string: "Hello"))
},
label: {
Text("Present Detail View")
}
)
}
}, detail: {
NavigationStack(path: self.$viewModel.navigationPath) {
Group {
Text("This is the detail base view.")
}
.navigationDestination(for: MyType.self) { data in
MyDestination (
text: data.string,
onBackPressed: {
if(self.$viewModel.navigationPath.wrappedValue.count > 0) {
self.$viewModel.navigationPath.wrappedValue.removeLast()
}
},
onNextPressed: {
self.$viewModel.navigationPath.wrappedValue.append(MyType(string: "This is the next thing"))
}
)
}
}
}
)
.navigationSplitViewStyle(.balanced)
.environmentObject(self.viewModel)
}
}
@available(iOS 16.0, *)
struct ContentView: View {
var body: some View {
MyNavigationView().environmentObject(MyNavigationViewModel())
}
}
@available(iOS 16.0, *)
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}