When remove intermediate screen from path I expect the same behaviour like removing view controller from UINavigationController.viewControllers
in UIKit
.
But now it evoke pop animation and recreate associated StateObject
.
It looks like instead of remove specific view controller in hierarchy, it removes the last one and change content on previous.
Code example to reproduce (Open Screen1
, then Screen2
and touch Pop previous
button):
enum Screen: String {
case screen1
case screen2
}
struct ContentView: View {
@State var path: [Screen] = []
var body: some View {
NavigationStack(path: $path) {
VStack {
Text("Root")
Button("open Screen 1") {
path.append(.screen1)
}
}
.navigationDestination(for: Screen.self) {
switch $0 {
case .screen1: ScreenView1(path: $path)
case .screen2: ScreenView2(path: $path)
}
}
}
}
}
struct ScreenView1: View {
@Binding var path: [Screen]
var body: some View {
VStack {
Text("Screen 1")
Button("Pop") { path.removeLast() }
Button("open Screen 2") { path.append(.screen2) }
}
}
}
struct ScreenView2: View {
@Binding var path: [Screen]
@StateObject var viewModel: Screen2ViewModel = .init()
var body: some View {
VStack {
Text("Screen 2")
Button("Pop") { path.removeLast() }
Button("Pop previous") {
// !!! Here the problem
path.remove(at: path.count - 2)
}
.disabled(path.count < 2)
}
}
}
class Screen2ViewModel: ObservableObject {
init() {
print("Screen2ViewModel.init")
}
}
Screencast:
It is possible to avoid pop animation by modifying path in transaction without animation:
var transaction = Transaction()
transaction.disablesAnimations = true
withTransaction(transaction) {
path.remove(at: path.count - 2)
}
But my question is: it is possible to avoid screen associated StateObject
recreating?