1

While testing my app to make sure it behaves properly under screen rotations, I discovered that navigation links do not work after a certain sequence of rotations.

The following is a MWE:

struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink("link") {
                Text("hi")
            }
        }
    }
    // rotate ->  back -> link -> rotate -> back -> link
}

On a iPhone 13 Pro Max (iOS 15.2 (19C51)) simulator, the following leads to an error:

  1. Run the app on the portrait mode
  2. Rotate the app to the landscape mode
  3. Touch the back button (in the navigation bar)
  4. Touch the navigation link link
  5. Rotate the app to the portrait mode
  6. Touch the back button
  7. Now touching the navigation link link does not work!

Also, the debug console prints:

Unbalanced calls to begin/end appearance transitions for <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentGS1_VVS_22_VariadicView_Children7ElementVS_24NavigationColumnModifier_GVS_18StyleContextWriterVS_19SidebarStyleContext___: 0x152f24860>.

Is this a bug in SwiftUI? And is there a way to work around this issue?

I'm on macOS Monterey (12.2 (21D49)) + Xcode 13.2.1 (13C100).

1
  • try to add this .navigationViewStyle(.stack) for your NavigationView Commented Jan 31, 2022 at 6:11

3 Answers 3

2

Without having to give up double column layout in iPadOS, I used the following conditional view builder to use different navigation style based on the horizontal size class.

(Although conditional view builders often do not play well with animations, it seems ok to use it here.)

extension View {
    @ViewBuilder func `if`<TrueContent: View>(
        _ condition: Bool,
        then trueContent: (Self) -> TrueContent
    ) -> some View {
        if condition {
            trueContent(self)
        } else {
            self
        }
    }
}

struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink("link") {
                Text("hi")
            }
        }
        .if(UIDevice.current.userInterfaceIdiom == .phone) {
            $0.navigationViewStyle(.stack)
        }
    }
}

P.S. The issue can be reproduced in iPadOS as well when the scene is resized appropriately after each rotation, but I think this is less likely to happen without intention to reproduce.

Sign up to request clarification or add additional context in comments.

Comments

1

Changing ColumnNavigationViewStyle to StackNavigationViewStyle will solve your problem, the sequence you mentioned is most probably a bug, hopefully apple will solve it soon.

struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink("link") {
                Text("hi")
            }
        }
        .navigationViewStyle(.stack) //Style
    }
}

2 Comments

Filed the issue FB9868662
Thank you. Was arleady looking to change our whole setup with UIHostingController because of this bug
0

The max uses columns in landscape and you are missing the second column View. Try this

struct ContentView: View {
var body: some View {
    NavigationView {
        NavigationLink("link") {
            Text("hi")
        }
         Text("Select a link")
    }
}
}

1 Comment

The issue persists with the above change.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.