SwiftUI:pushViewController:animated:在现有过渡或演示发生时调用...
SwiftUI: pushViewController:animated: called on ... while an existing transition or presentation is occurring
我想从警报中导航到详细信息视图。
这里是错误的最小可重现代码示例:
struct ContentView: View {
let items = ["1", "2", "3", "4"]
var body: some View {
NavigationView {
List {
ForEach(items, id: \.self) { item in
RowView(item: item)
}
}
}
}
}
struct RowView: View {
let item: String
@State private var isShowingNext = false
@State private var isShowingAlert = false
var body: some View {
let itemNumber = Int(item)!
let isEven = itemNumber % 2 == 0
ZStack {
if isEven {
NavigationLink(
destination: Text("Hello"),
isActive: $isShowingNext,
label: {
Text(item)
}
).hidden()
Button(
action: {
isShowingAlert.toggle()
}, label: {
Text("\(item) (with alert)")
}
)
.alert(isPresented: $isShowingAlert) {
Alert(
title: Text("Alert")
.foregroundColor(Color.red)
.font(.title),
message: Text("Hello"),
primaryButton: .destructive(
Text("Navigate"),
action: {
isShowingNext = true
}
),
secondaryButton: .cancel()
)
}
} else {
NavigationLink(
destination: Text("Hello"),
isActive: $isShowingNext,
label: {
Text(item)
}
)
}
}
}
}
当您点击例如项目 2 (with alert)
警报出现,但错误也出现在控制台中。然后,当您在警报中单击 Navigate
时,它不会导航。
可能是什么问题?
Alert
和NavigationLink
都呈现了另一种观点。当另一个视图已经显示在当前视图上时,您不能显示一个视图。
您必须等到 Alert
被隐藏,然后您才能显示 NavigationLink
。
最简单的方法是将 Binding
传递给 NavigationLink
,这将确保 Alert
不显示:
struct RowView: View {
let item: String
@State private var isShowingNext = false
@State private var isShowingAlert = false
private var isShowingNextBinding: Binding<Bool> {
Binding(
get: {
!isShowingAlert && isShowingNext
}, set: {
isShowingNext = [=10=]
}
)
}
var body: some View {
let itemNumber = Int(item)!
let isEven = itemNumber % 2 == 0
ZStack {
if isEven {
NavigationLink(
destination: Text("Hello"),
isActive: isShowingNextBinding,
label: {
Text(item)
}
).hidden()
Button(
action: {
isShowingAlert.toggle()
}, label: {
Text("\(item) (with alert)")
}
)
.alert(isPresented: $isShowingAlert) {
Alert(
title: Text("Alert")
.foregroundColor(Color.red)
.font(.title),
message: Text("Hello"),
primaryButton: .destructive(
Text("Navigate"),
action: {
isShowingNext = true
}
),
secondaryButton: .cancel()
)
}
} else {
NavigationLink(
destination: Text("Hello"),
isActive: $isShowingNext,
label: {
Text(item)
}
)
}
}
}
}
我想从警报中导航到详细信息视图。
这里是错误的最小可重现代码示例:
struct ContentView: View {
let items = ["1", "2", "3", "4"]
var body: some View {
NavigationView {
List {
ForEach(items, id: \.self) { item in
RowView(item: item)
}
}
}
}
}
struct RowView: View {
let item: String
@State private var isShowingNext = false
@State private var isShowingAlert = false
var body: some View {
let itemNumber = Int(item)!
let isEven = itemNumber % 2 == 0
ZStack {
if isEven {
NavigationLink(
destination: Text("Hello"),
isActive: $isShowingNext,
label: {
Text(item)
}
).hidden()
Button(
action: {
isShowingAlert.toggle()
}, label: {
Text("\(item) (with alert)")
}
)
.alert(isPresented: $isShowingAlert) {
Alert(
title: Text("Alert")
.foregroundColor(Color.red)
.font(.title),
message: Text("Hello"),
primaryButton: .destructive(
Text("Navigate"),
action: {
isShowingNext = true
}
),
secondaryButton: .cancel()
)
}
} else {
NavigationLink(
destination: Text("Hello"),
isActive: $isShowingNext,
label: {
Text(item)
}
)
}
}
}
}
当您点击例如项目 2 (with alert)
警报出现,但错误也出现在控制台中。然后,当您在警报中单击 Navigate
时,它不会导航。
可能是什么问题?
Alert
和NavigationLink
都呈现了另一种观点。当另一个视图已经显示在当前视图上时,您不能显示一个视图。
您必须等到 Alert
被隐藏,然后您才能显示 NavigationLink
。
最简单的方法是将 Binding
传递给 NavigationLink
,这将确保 Alert
不显示:
struct RowView: View {
let item: String
@State private var isShowingNext = false
@State private var isShowingAlert = false
private var isShowingNextBinding: Binding<Bool> {
Binding(
get: {
!isShowingAlert && isShowingNext
}, set: {
isShowingNext = [=10=]
}
)
}
var body: some View {
let itemNumber = Int(item)!
let isEven = itemNumber % 2 == 0
ZStack {
if isEven {
NavigationLink(
destination: Text("Hello"),
isActive: isShowingNextBinding,
label: {
Text(item)
}
).hidden()
Button(
action: {
isShowingAlert.toggle()
}, label: {
Text("\(item) (with alert)")
}
)
.alert(isPresented: $isShowingAlert) {
Alert(
title: Text("Alert")
.foregroundColor(Color.red)
.font(.title),
message: Text("Hello"),
primaryButton: .destructive(
Text("Navigate"),
action: {
isShowingNext = true
}
),
secondaryButton: .cancel()
)
}
} else {
NavigationLink(
destination: Text("Hello"),
isActive: $isShowingNext,
label: {
Text(item)
}
)
}
}
}
}