IOS 26.1: In TabView wird die NavigationStack-Animation unterbrochen, wenn die Tab-Auswahl abgefangen wird, um FullScreeIOS

Programmierung für iOS
Anonymous
 IOS 26.1: In TabView wird die NavigationStack-Animation unterbrochen, wenn die Tab-Auswahl abgefangen wird, um FullScree

Post by Anonymous »

Ich versuche, ein FullScreenCover anzuzeigen, wenn der Benutzer auf die dritte Registerkarte tippt, anstatt tatsächlich zu dieser Registerkarte zu wechseln. Das Problem besteht darin, dass das Zurücksetzen von selectedTab = oldValue in onChange die NavigationStack-Push/Pop-Animationen im vorherigen Tab unterbricht.
Das Problem
Wenn ich die Tab-Auswahl synchron zurücksetze, verliert der NavigationStack im vorherigen Tab seine Animationen – keine Push/Pop-Übergänge funktionieren mehr, bis ich die Tabs weg- und zurückwechsele.
Defekter Code:

Code: Select all

struct ContentView: View {
@State private var selectedTab: Int = 0
@State private var showSheet: Bool = false

var body: some View {
TabView(selection: $selectedTab) {
Tab("First", systemImage: "1.circle.fill", value: 0) {
FirstTabView()
}
Tab("Second", systemImage: "2.circle.fill", value: 1) {
SecondTabView()
}
Tab("Sheet", systemImage: "ellipsis", value: 2, role:.search) {
EmptyView()
}
}
.onChange(of: selectedTab) { oldValue, newValue in
if newValue == 2 {
showSheet = true
selectedTab = oldValue  // This breaks NavigationStack animations!
}
}
.fullScreenCover(isPresented: $showSheet) {
SheetView()
}
}
}
Defekte Navigationsanimation hier: https://youtube.com/shorts/SeBlTQxbV68
Die Problemumgehung
Das Hinzufügen einer kleinen Verzögerung vor dem Zurücksetzen der Tab-Auswahl scheint das Problem zu beheben:

Code: Select all

.onChange(of: selectedTab) { oldValue, newValue in
if newValue == 2 {
Task { @MainActor in
showSheet = true
try? await Task.sleep(for: .seconds(0.25))
selectedTab = oldValue
}
}
}
Arbeitet mit Verzögerung: https://youtube.com/shorts/B4AbX72vc3g
Vollständig reproduzierbarer Code

Code: Select all

import SwiftUI

struct FirstTabView: View {
var body: some View {
NavigationStack {
VStack {
Text("Basic View")
}
}
}
}

struct SecondTabView: View {
@State private var items: [String] = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"]

var body: some View {
NavigationStack {
List(items, id: \.self) { item in
NavigationLink(value: item) {
Text(item)
}
}
.navigationTitle("Second Tab")
.navigationBarTitleDisplayMode(.inline)
.navigationDestination(for: String.self) { item in
Text(item)
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
items.append("Item \(items.count + 1)")
}) {
Image(systemName: "plus")
}
}
}
}
}
}

struct SheetView: View {
@Environment(\.dismiss) private var dismiss

var body: some View {
NavigationStack {
VStack {
Text("Hello World")
}
.navigationTitle("Sheet View")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
dismiss()
}) {
Image(systemName: "xmark")
}
}
}
}
}
}

struct ContentView: View {
@State private var selectedTab: Int = 0
@State private var showSheet: Bool = false

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

#Preview {
ContentView()
}
Fragen
  • Warum unterbricht das synchrone Zurücksetzen NavigationStack-Animationen?
  • Gibt es eine sauberere Lösung, die keine hartcodierte Verzögerung erfordert?
  • Ist dies ein bekannter iOS 26-Fehler mit TabView und NavigationStack?
Umgebung: iOS 26.1, Xcode 26.1

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post