Xcode: Version 12.1 (12A7403)
iOS: 14.x
I have run into this weird bug where the navigation bar "back button" disappears when a child view updates the list used by the navigation view's root list. I've put together some MVP code to demo the bug:
So far, I've only encountered it on the iPhone in landscape mode. The button doesn't disappear when in landscape mode (for iPhones that support the larger iPad-like layout), iPads in both orientations, and MacOS. I haven't tested on WatchOS. It happens in the Xcode live preview, simulator, and on device.
I have found some mitigations that don't work for my use case. For example, it works when I replace the button closure with a method on either the view or env object:
But it still breaks when calling the method through a closure:
It must have something to do with the closure updating the env object. I'm more just surprised to find this happing in one specific use case, but it happens to be exactly how most users would interact with the app.
iOS: 14.x
I have run into this weird bug where the navigation bar "back button" disappears when a child view updates the list used by the navigation view's root list. I've put together some MVP code to demo the bug:
Code Block swift import SwiftUI class ItemStore: ObservableObject { @Published var items = [Int]() init(items: [Int]) { self.items = items} } struct ContentView: View { @EnvironmentObject var store: ItemStore var body: some View { NavigationView { List { ForEach(store.items, id: \.self) { label in NavigationLink(destination: Child1(label: label)) { Text(String(label)) } } } } } } struct Child1: View { var label: Int var body: some View { List { NavigationLink(destination: Child2(label: label)) { Text("Child1: \(label)") } } } } struct Child2: View { @EnvironmentObject var store: ItemStore var label: Int var body: some View { Text("Child2: \(label)") .toolbar { Button(action: { let max = store.items.max() store.items.append(max == nil ? 1 : max! + 1) }) { Image(systemName: "plus") } } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() .environmentObject(ItemStore(items: [1,2,3])) } }
So far, I've only encountered it on the iPhone in landscape mode. The button doesn't disappear when in landscape mode (for iPhones that support the larger iPad-like layout), iPads in both orientations, and MacOS. I haven't tested on WatchOS. It happens in the Xcode live preview, simulator, and on device.
I have found some mitigations that don't work for my use case. For example, it works when I replace the button closure with a method on either the view or env object:
Code Block swift struct Child2: View { @EnvironmentObject var store: ItemStore var label: Int func increment() { let max = store.items.max() store.items.append(max == nil ? 1 : max! + 1) } var body: some View { Text("Child2: \(label)") .toolbar { Button(action: increment) { Image(systemName: "plus") } } } }
But it still breaks when calling the method through a closure:
Code Block swift Button(action: { increment() }) {
It must have something to do with the closure updating the env object. I'm more just surprised to find this happing in one specific use case, but it happens to be exactly how most users would interact with the app.