这是可能的。尽管您不需要跟踪与您一样多的状态。
首先,您只需跟踪它们是否失败。因此,您的failedRegister
将跟踪用户是否成功注册。这意味着我们可以删除successfulRegister
。
我们需要一个变量来跟踪是否正在显示警报,为此,我们将使用变量showAlert
。
由于您有提供userinfo的链接列表,因此我们将使用仅包含一些用户名的数组进行模拟。
这是您的代码的简化版本,应该可以正常工作。
struct ContentView: View {
var names: [String] = ["John", "Mike"]
@State var username: String = ""
@State var password : String = ""
@State private var failedRegister = false
@State private var showAlert = false
var body: some View {
VStack {
TextField("Enter username", text: $username)
Button(action: {
self.failedRegister = false
if (self.names.contains(self.username)){
self.failedRegister.toggle()
} else {
}
self.showAlert.toggle()
}) {
Text("Register")
.font(.headline)
.foregroundColor(.white)
.padding()
.frame(width: 220, height: 60)
.background(Color.green)
.cornerRadius(15.0)
}
}.alert(isPresented: $showAlert) {
if self.failedRegister {
return Alert(title: Text("Failed to register"), message: Text("Unfortunately that username is taken"), dismissButton: .default(Text("OK")))
} else {
return Alert(title: Text("Welcome"), message: Text("You have registered"), dismissButton: .default(Text("OK")))
}
}
}
}
使用Identifiable进行更新
有一种在同一个View
上显示不同Alerts
的替代方法,那就是使用绑定到具有Identifiable
属性的对象。
如果我们看一下在View
上初始化Alert
的方式,我们可以看到有两种方式。第一种的签名如下:
.alert(isPresented: Binding<Bool>, content: () -> Alert)
这是上面示例中使用的方法。
然而,还有一种另外的方式,其签名如下:
.alert(item: Binding<Identifiable?>, content: (Identifiable) -> Alert)
第二种方式可以管理更复杂的警报。要使用它,我们需要跟踪警报状态的内容。我们可以创建一个简单的结构体来符合 Identifiable
并包含警报的不同选择的枚举。
然后我们创建一个 @State
变量来跟踪 AlertIdentifier
,并初始化为 nil
,这样它的状态就为空,并且在更改之前不会显示任何警报。
然后我们可以在 View
中添加我们的 .alert(item:content:)
。
以下是一个简单的示例,展示了它的实际运用。
struct ContentView:View {
private struct AlertIdentifier: Identifiable {
var id: Choice
enum Choice {
case success
case failure
}
}
@State private var showAlert: AlertIdentifier?
var body: some View {
VStack(spacing: 20) {
Button(action: {
self.showAlert = AlertIdentifier(id: .success)
}, label: {
Text("Show success alert")
})
Button(action: {
self.showAlert = AlertIdentifier(id: .failure)
}, label: {
Text("Show failure alert")
})
}
.alert(item: $showAlert) { alert -> Alert in
switch alert.id {
case .success:
return Alert(title: Text("Success"), message: Text("You have successfully registered"), dismissButton: .default(Text("OK")))
case .failure:
return Alert(title: Text("Failure"), message: Text("You have failed to register"), dismissButton: .default(Text("OK")))
}
}
}
}
请注意,在按钮中,我们将 showAlert
设置为 AlertIdentifier
结构体的一个实例,具有我们想要显示的警报类型。在这种情况下,我们有两种类型:成功和失败(但我们可以有任意数量的类型,并且不需要使用名称success 和failure)。设置了此项后,它将显示相应的警报。
在我们的 .alert(item:content :)
中,我们切换不同的id
,以确保正确的选择显示正确的警报。
这种方法比拥有多个布尔变量更简单,而且更容易扩展。
用于 Sheets 和 ActionSheets 的补充说明
Sheets
和 ActionSheets
在它们的呈现方式上非常类似于 Alerts
。有四种方法来展示 Sheets
。
这两个需要一个 Bool
绑定:
.sheet(isPresented: Binding<Bool>, content: () -> View)
.sheet(isPresented: Binding<Bool>, onDismiss: (() -> Void)?, content: () -> Void)
这两个需要一个 Identifiable
绑定:
.sheet(item: Binding<Identifiable?>, content: (Identifiable) -> View)
.sheet(item: Binding<Identifiable?>, onDismiss: (() -> Void)?, content: (Identifiable) -> View)
对于ActionSheets
,有两种方式,就像Alerts
一样。
通过Bool
绑定:
.actionSheet(isPresented: Binding<Bool>, content: () -> ActionSheet)
通过 Identifiable
绑定:
.actionSheet(item: Binding<Identifiable?>, content: (Identifiable) -> ActionSheet)
我应该使用哪种绑定方式?
Binding<Bool>
如果您只需要显示一种类型的Alert
、Sheet
或ActionSheet
,则使用Bool
绑定,可以节省写额外代码的麻烦。
Binding<Identifiable?>
如果您有多种不同类型的Alert
、Sheet
或ActionSheet
需要显示,则选择Identifiable
绑定,它可以使管理变得更加容易。
一个更简单的可识别对象
一个更简单的可识别对象的版本是使用枚举而不是将其包装在结构体中。在这种情况下,我们需要符合Identifiable
协议,因此我们需要一个计算属性来存储id值。我们还需要确保枚举使用RawRepresentable,以便我们可以获得唯一的id值。我建议使用Int或String。在下面的示例中,我使用了Int。
enum Choice: Int, Identifiable {
var id: Int {
rawValue
}
case success, failure
}
然后在视图中,我们可以执行以下操作:
struct ContentView:View {
enum Choice: Int, Identifiable {
var id: Int {
rawValue
}
case success, failure
}
@State private var showAlert: Choice?
var body: some View {
VStack(spacing: 20) {
Button(action: {
self.showAlert = .success
}, label: {
Text("Show success alert")
})
Button(action: {
self.showAlert = .failure
}, label: {
Text("Show failure alert")
})
}
.alert(item: $showAlert) { alert -> Alert in
switch alert {
case .success:
return Alert(title: Text("Success"), message: Text("You have successfully registered"), dismissButton: .default(Text("OK")))
case .failure:
return Alert(title: Text("Failure"), message: Text("You have failed to register"), dismissButton: .default(Text("OK")))
}
}
}
}
.alert(isPresented: $failedRegister || $sucessfulRegister)
,那就太好了。 - Learn2CodeBinding<Identifiable?>
而不是Binding<Bool>
。我已经在我的原始答案中添加了一个示例,展示了如何使用它。希望你觉得有用。 - Andrew