HomeiOS Developmentswift - iOS 26.1: In TabView, NavigationStack animation breaks when intercepting tab...

swift – iOS 26.1: In TabView, NavigationStack animation breaks when intercepting tab choice to indicate fullScreenCover


I am attempting to indicate a fullScreenCover when the consumer faucets the third tab as an alternative of really switching to that tab. The difficulty is that resetting selectedTab = oldValue in onChange breaks the NavigationStack push/pop animations within the earlier tab.

After I reset the tab choice synchronously, the NavigationStack within the earlier tab loses its animations – no push/pop transitions work anymore till I swap tabs away and again.

Damaged code:

struct ContentView: View {
  @State non-public var selectedTab: Int = 0
  @State non-public var showSheet: Bool = false

  var physique: some View {
    TabView(choice: $selectedTab) {
      Tab("First", systemImage: "1.circle.fill", worth: 0) {
        FirstTabView()
      }
      Tab("Second", systemImage: "2.circle.fill", worth: 1) {
        SecondTabView()
      }
      Tab("Sheet", systemImage: "ellipsis", worth: 2, function:.search) {
        EmptyView()
      }
    }
    .onChange(of: selectedTab) { oldValue, newValue in
      if newValue == 2 {
        showSheet = true
        selectedTab = oldValue  // This breaks NavigationStack animations!
      }
    }
    .fullScreenCover(isPresented: $showSheet) {
      SheetView()
    }
  }
}

Damaged navigation animation right here: https://youtube.com/shorts/SeBlTQxbV68

Including a small delay earlier than resetting the tab choice appears to repair it:

.onChange(of: selectedTab) { oldValue, newValue in
  if newValue == 2 {
    Activity { @MainActor in
      showSheet = true
      attempt? await Activity.sleep(for: .seconds(0.25))
      selectedTab = oldValue
    }
  }
}

Working with delay: https://youtube.com/shorts/B4AbX72vc3g

import SwiftUI

struct FirstTabView: View {
  var physique: some View {
    NavigationStack {
      VStack {
        Textual content("Fundamental View")
      }
    }
  }
}

struct SecondTabView: View {
  @State non-public var gadgets: [String] = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"]

  var physique: some View {
    NavigationStack {
      Listing(gadgets, id: .self) { merchandise in
        NavigationLink(worth: merchandise) {
          Textual content(merchandise)
        }
      }
      .navigationTitle("Second Tab")
      .navigationBarTitleDisplayMode(.inline)
      .navigationDestination(for: String.self) { merchandise in
        Textual content(merchandise)
      }
      .toolbar {
        ToolbarItem(placement: .navigationBarTrailing) {
          Button(motion: {
            gadgets.append("Merchandise (gadgets.depend + 1)")
          }) {
            Picture(systemName: "plus")
          }
        }
      }
    }
  }
}

struct SheetView: View {
  @Atmosphere(.dismiss) non-public var dismiss

  var physique: some View {
    NavigationStack {
      VStack {
        Textual content("Good day World")
      }
      .navigationTitle("Sheet View")
      .navigationBarTitleDisplayMode(.inline)
      .toolbar {
        ToolbarItem(placement: .navigationBarTrailing) {
          Button(motion: {
            dismiss()
          }) {
            Picture(systemName: "xmark")
          }
        }
      }
    }
  }
}

struct ContentView: View {
  @State non-public var selectedTab: Int = 0
  @State non-public var showSheet: Bool = false

  var physique: some View {
    TabView(choice: $selectedTab) {
      Tab("First", systemImage: "1.circle.fill", worth: 0) {
        FirstTabView()
      }
      Tab("Second", systemImage: "2.circle.fill", worth: 1) {
        SecondTabView()
      }
      Tab("Sheet", systemImage: "ellipsis", worth: 2, function:.search) {
        EmptyView()
      }
    }
    .onChange(of: selectedTab) { oldValue, newValue in
      if newValue == 2 {
        Activity { @MainActor in
          showSheet = true
          attempt? await Activity.sleep(for: .seconds(0.25))
          selectedTab = oldValue
        }
      }
    }
    .fullScreenCover(isPresented: $showSheet) {
      SheetView()
    }
  }
}

#Preview {
  ContentView()
}
  1. Why does the synchronous reset break NavigationStack animations?
  2. Is there a cleaner answer that does not require a hardcoded delay?
  3. Is that this a recognized iOS 26 bug with TabView and NavigationStack?

Atmosphere: iOS 26.1, Xcode 26.1

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments