Проблема
Когда я синхронно сбрасываю выбор вкладок, NavigationStack на предыдущей вкладке теряет свою анимацию - никакие переходы push/pop больше не работают, пока я не переключу вкладки обратно и обратно.
Неверный код:
Код: Выделить всё
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()
}
}
}
Обходное решение
Добавление небольшой задержки перед сбросом выбора вкладок, кажется, исправляет проблему:
Код: Выделить всё
.onChange(of: selectedTab) { oldValue, newValue in
if newValue == 2 {
Task { @MainActor in
showSheet = true
try? await Task.sleep(for: .seconds(0.25))
selectedTab = oldValue
}
}
}
Полный воспроизводимый код
Код: Выделить всё
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()
}
- Почему синхронный сброс нарушает анимацию NavigationStack?
- Существует ли более чистое решение, не требующее жестко запрограммированной задержки?
- Известна ли это ошибка iOS 26 с TabView и NavigationStack?
Подробнее здесь: https://stackoverflow.com/questions/798 ... ng-tab-sel
Мобильная версия