警报从应用程序的任何视图显示,而不是仅从其父视图显示



我有一个主选项卡栏,它有三个选项卡,在第一个选项卡中,我有一项可能返回错误的后台任务,此错误由警报视图显示。现在,如果我在后台任务运行时移动到应用程序中的任何选项卡视图,并且发生错误,则警报将显示在当前视图中,而不是显示在第一个选项卡视图中。

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")
}
}
}
}

一种处理方法是在错误发生时更新第一个选项卡上的徽章图标。然后,用户可以完成他们当前正在做的事情,然后在注意到第一个选项卡已更新时检查它,比如使用感叹号徽章。此时,您可以发出警报。

最新更新