我有一个主选项卡栏,它有三个选项卡,在第一个选项卡中,我有一项可能返回错误的后台任务,此错误由警报视图显示。现在,如果我在后台任务运行时移动到应用程序中的任何选项卡视图,并且发生错误,则警报将显示在当前视图中,而不是显示在第一个选项卡视图中。
struct FirstTabView: View {
// viewModel will fire the background task after init
@StateObject var viewModel: FirstViewModel = .init()
var body: some View {
Text("Hello First")
.alert("error", isPresented: .init(get: {
return viewModel.errorMessage != nil
}, set: { _ in
viewModel.errorMessage = nil
})) {
Button("OK") {
}
}
}
}
如何限制错误警报仅显示在第一个选项卡上?
一个解决方案可以将警报移动到主TabView
,而不是在子视图中显示。通过这样做,您将能够跟踪选择了哪个选项卡,并仅在两种情况都成立时触发警报:
- 选择第一个选项卡
- 视图模型的属性
errorMessage
不为零
触发器是TabView
视图中的专用showAlert
状态属性,每当屏幕上出现第一个选项卡时,该属性就会更改。
在下面的示例中,您可以从第二个视图更改视图模型的属性,但只有当您移动到第一个选项卡时才会显示警报;我希望这就是你想要的:
// The model must be an observable class
class MyModel: ObservableObject {
// The error message must be a published property
@Published var errorMessage: String? = nil
}
struct MyTabs: View {
// viewModel will fire the background task after init
let viewModel = MyModel() // Use your ViewModel as applicable
@State private var tabSelection = 0 // This property will track the selected tab
@State private var showAlert = false // This property is the trigger to the alert
var body: some View {
TabView(selection: $tabSelection) { // The selection: parameter tracks the selected tab through the .tag()
FirstTabView()
.environmentObject(viewModel) // Pass the same model to the Views in each tab
.tabItem { Text("First") }
.tag(0) // This is View #0 for the tabSelection property
.onAppear {
// Only when this View appears the showAlert will be set to true,
// only if there is an error in the model's property and the first tab is selected
if viewModel.errorMessage != nil && tabSelection == 0 {
showAlert = true
}
}
Second()
.environmentObject(viewModel) // Pass the same model to the Views in each tab
.tabItem { Text("Second") }
.tag(1) // This is View #1 for the tabSelection property
}
// Trigger the alert in the TabView, instead of in the child View
.alert("error", isPresented: $showAlert) {
Button {
viewModel.errorMessage = nil
} label: {
Text("OK")
}
} message: {
Text(viewModel.errorMessage ?? "not available")
}
}
}
struct FirstTabView: View {
@EnvironmentObject var viewModel: MyModel
var body: some View {
VStack {
Text("Hello First")
.padding()
Text("(viewModel.errorMessage ?? "OK")")
.padding()
}
}
}
struct Second: View {
@EnvironmentObject var viewModel: MyModel
var body: some View {
VStack {
Text("Second")
.padding()
Text("(viewModel.errorMessage ?? "OK")")
.padding()
Button {
viewModel.errorMessage = "error"
} label: {
Text("Show alert")
}
}
}
}
一种处理方法是在错误发生时更新第一个选项卡上的徽章图标。然后,用户可以完成他们当前正在做的事情,然后在注意到第一个选项卡已更新时检查它,比如使用感叹号徽章。此时,您可以发出警报。