在 Alert 被弃用之前,我曾经通过引入 AlertState 来管理视图的不同警报:
enum AlertState: Identifiable {
case associatedIngredient
case confirmDelete
var id: AlertState { self }
}
在我看来,我有变量
@State private var activeAlert: FoodItemViewSheets.AlertState?
我将设置 AlertState:
// Delete the food item
Button("Delete", systemImage: "trash") {
if foodItemVM.hasAssociatedFoodItem() {
// Check if FoodItem is related to an Ingredient
if !foodItemVM.canBeDeleted() {
self.activeAlert = .associatedIngredient
} else {
self.activeAlert = .confirmDelete
}
}
}
...以及之后:
.alert(item: $activeAlert) {
alertContent($0)
}
此功能将发出正确的警报:
private func alertContent(_ state: AlertState) -> Alert {
switch state {
case .confirmDelete:
return Alert(
title: Text("Delete food"),
message: Text("Do you really want to delete this food item? This cannot be undone!"),
primaryButton: .default(
Text("Do not delete")
),
secondaryButton: .destructive(
Text("Delete"),
action: deleteFoodItemOnly
)
)
case .associatedIngredient:
return Alert(
title: Text("Cannot delete food"),
message: Text("This food item is in use in a recipe, please remove it from the recipe before deleting.")
)
}
}
不幸的是,警报已被弃用。
我想知道最好的方法是什么让这种行为(与同一按钮关联的两个不同警报)与新的alert(_:isPresented:presenting:actions:message:)实例方法一起使用。
欢迎任何想法!
您只需要一个额外的
@State
即可传递给 isPresented:
参数。其余的都非常不言自明。您只需使用 switch
语句来提供标题、消息和操作,就像您已经在做的那样。只是你返回的是View
,而不是Alert
。
@State private var alertPresented = false
@State private var activeAlert: AlertState?
// this flag controls which alert to show in this toy example
@State private var flag = false
var body: some View {
// as an example, I will use a toggle to control which alert to show
Toggle("", isOn: $flag)
Button("Delete", systemImage: "trash") {
if flag {
self.activeAlert = .associatedIngredient
} else {
self.activeAlert = .confirmDelete
}
}
.alert(alertTitle, isPresented: $alertPresented, presenting: activeAlert) {
alertActions(for: $0)
} message: {
alertMessage(for: $0)
}
.onChange(of: activeAlert) { oldValue, newValue in
if oldValue == nil && newValue != nil {
alertPresented = true
} else if oldValue != nil && newValue == nil {
alertPresented = false
}
}
}
@ViewBuilder
func alertMessage(for alert: AlertState) -> some View {
switch alert {
case .associatedIngredient:
Text("Do you really want to delete this food item? This cannot be undone!")
case .confirmDelete:
Text("This food item is in use in a recipe, please remove it from the recipe before deleting.")
}
}
@ViewBuilder
func alertActions(for alert: AlertState) -> some View {
switch alert {
case .associatedIngredient:
Button("OK", role: .cancel) {}
case .confirmDelete:
Button("Do not delete", role: .cancel) { }
Button("Delete", role: .destructive) {
// ...
}
}
}
var alertTitle: String {
switch activeAlert {
case .associatedIngredient:
"Cannot delete food"
case .confirmDelete:
"Delete food"
case nil:
""
}
}