1

Discovered in my app that navigation bar items in some views disappear when orientation of the device changes. This seems to occur only in a view that is opened using NavigationLink, on main view navigation bar items work as expected. It appears that something has changed between iOS 13.7 and iOS 14.2 related to this. Also, it does not seem to matter whether using leading or trailing items, both disappear.

Example snippet where this occurs:

struct ContentView: View {
    var detailView: some View {
        Text("This is detail view")
            .navigationBarTitle("Detail view title", displayMode: .inline)
            .navigationBarItems(trailing: Button(action: {}, label: {
                Image(systemName: "pencil.circle.fill")
            }))
    }

    var body: some View {
        NavigationView {
            NavigationLink(
                destination: detailView,
                label: {
                    Text("Open detail view")
                })
                .navigationBarTitle("Main view")
        }.navigationViewStyle(StackNavigationViewStyle())
    }
}

Here's what happens

The issue occurs only when running on a real device. (iPhone 11 in my case) On simulator everything works as expected.

Anyone else seen similar issues? Workarounds/fixes?

AaaK00
  • 41
  • 1
  • 6
  • A similar issue happened with me a few weeks ago. UIBarButtonItems not showing images specifically. Can you confirm the simulators and your device are running the same version of iOS? As this was the fix my issue. – CSmizzle Dec 08 '20 at 09:56
  • Yeap, my simulator and iPhone are both running iOS 14.2. Also, it does not matter what is the type of the view that is added as navigationBarItem. Even if it contains just a Text view it behaves similarly and view is hidden when orientation changes. – AaaK00 Dec 08 '20 at 12:42
  • Apologies, I meant the actual UIImage property one can pass in as a parameter when declaring a fully-loaded UIBarButtonItem instance. For instance, "< Back" (with the left arrow chevron) UIImage would show on the simulator, while just the text "Back" would show on my device. – CSmizzle Dec 08 '20 at 13:39
  • But, seeing as how updating isn't your issue, have you tried a brute force override of the BarButtonItem giving the issue in detailView just to see if it works? – CSmizzle Dec 08 '20 at 13:44
  • Could you please clarify what you mean by "brute force override of the BarButtonItem giving the issue in detailView just to see if it works?" – AaaK00 Dec 09 '20 at 13:36
  • self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(systemName: "pencil.circle.fill"), style: .done, target: self, action: #selector(yourSelectorFunction)) – CSmizzle Dec 10 '20 at 19:18
  • in viewDidLoad() for your detailView class – CSmizzle Dec 10 '20 at 19:19

3 Answers3

3

.navigationBarTitle and .navigationBarItems are being deprecated. I think that the best "fix" is to switch to .toolbar

lorem ipsum
  • 21,175
  • 5
  • 24
  • 48
  • That would probably solve the issue. Unfortunately that is not yet possible for me since we are still using Xcode 11 for submitting builds to app store. (Some external libraries have issues with Xcode 12) – AaaK00 Dec 08 '20 at 13:33
  • I'm using `navigationTitle`, which is not deprecated-- but still seeing the nav bar items disappear. Doesn't seem rotation related. So far I'm seeing it only on on iPad. – Chris Prince Jun 29 '21 at 01:44
0

It's a weird issue but I guess there is a hack to make it work. SwiftUI doesn't call body property when rotations happen. So you can add @State UIDeviceOrientation property to your view and update it every time orientation changes. One tricky thing is to use that property somewhere in the body of the view since SwiftUI smart enough to ignore @State that is not used in the body.

struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink(
                destination: DetailsView(),
                label: {
                    Text("Open detail view")
                }).navigationBarTitle("Main view")
        }.navigationViewStyle(StackNavigationViewStyle())
    }
}
struct DetailsView: View {
    @State var orientation: UIDeviceOrientation = UIDevice.current.orientation

    var body: some View {
        Text("This is detail view")
            .navigationBarTitle("Detail view title")
            .navigationBarItems(trailing: button)
            .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
                orientation = UIDevice.current.orientation
            }.background(Text("\(orientation.rawValue)"))
    }

    var button: some View {
        Button(action: { print("123") }, label: {
            Image(systemName: "pencil.circle.fill")
        }).id("123")
    }
}
0

In my experience when I change a Button in the toolbar from disabled to enabled, they disappear. But if I scroll to the bottom of the View, they re-appear. If I am already at the end of the View when the button is enabled, it acts normally, until I then scroll away from the bottom, the button again disappears. Try scrolling to the bottom of your view, if you use landscape.

SteveP
  • 1