我在这里发布之前做了一些研究,但我无法修复它。
在注册视图中,我希望用户注册。
我创建了一个链表,当用户注册用户名时,我的程序会检查用户名是否已被占用。
如果被占用,它应该发出警报,说明用户名已被占用,因为用户点击了注册按钮。
如果用户名没有被占用,那么它应该显示一个警报,说注册成功
import SwiftUI
struct registerScreen: View {
@State var username: String = ""
@State var password: String = ""
@State private var sucessfulRegister = false
@State private var failedRegister = false
var body: some View {
VStack {
TextField()
SecureField()
Button(action: {
let userinfo = linkedList()
if (userinfo.contains(value: self.username)){
// self.failedRegister = true
self.failedRegister.toggle()
// show alert that it failed
} else {
userinfo.insert(value: user(username: self.username, password: self.password))
// show alert that it is successfull
self.sucessfulRegister.toggle()
}
})
{
Text("Register")
.font(.headline)
.foregroundColor(.white)
.padding()
.frame(width: 220, height: 60)
.background(Color.green)
.cornerRadius(15.0)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是可能的。尽管您不需要跟踪尽可能多的状态。
首先,您只需要跟踪它们是否失败。因此,您failedRegister将跟踪用户是否已成功注册。这意味着我们可以删除successfulRegister.
我们需要一个变量来跟踪警报是否显示,为此我们将使用变量 showAlert
由于您有一个提供用户信息的链表,我们将仅使用一个包含几个用户名的数组来模拟它。
所以这里是你的代码的简化版本,应该可以工作。
struct ContentView: View {
var names: [String] = ["John", "Mike"]
@State var username: String = ""
@State var password : String = ""
@State private var failedRegister = false
// this value is used for tracking whether the alert should be shown
@State private var showAlert = false
var body: some View {
VStack {
TextField("Enter username", text: $username)
Button(action: {
// reset to false as this is the initial state
self.failedRegister = false
if (self.names.contains(self.username)){
self.failedRegister.toggle()
} else {
// insert the value into the user info
}
self.showAlert.toggle()
}) {
Text("Register")
.font(.headline)
.foregroundColor(.white)
.padding()
.frame(width: 220, height: 60)
.background(Color.green)
.cornerRadius(15.0)
}
}.alert(isPresented: $showAlert) {
// it would be nice to set failedRegister back to false in this function but you cannot modify state here.
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")))
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
有一种替代方法可以Alerts在同一个View. 这是使用对Identifiable.
如果我们看看我们可以Alert在 a 上初始化 an 的方法,我们会View发现有两种方法。第一个具有以下签名:
.alert(isPresented: Binding<Bool>, content: () -> Alert)
Run Code Online (Sandbox Code Playgroud)
这就是上面示例中使用的内容。
但是,还有第二种方式具有以下签名:
.alert(item: Binding<Identifiable?>, content: (Identifiable) -> Alert)
Run Code Online (Sandbox Code Playgroud)
第二种方式可以允许管理更复杂的警报。为了利用这一点,我们需要一些东西来跟踪警报的状态。我们可以创建一个简单的结构,它符合Identifiable并包含我们对警报的不同选择的枚举。
然后我们创建一个@State变量来跟踪AlertIdentifier和初始化nil,使其状态为空,并且在更改之前不会显示任何警报。
然后我们可以将我们的添加.alert(item:content:)到我们的View.
这是一个简单的例子,展示了它的实际效果。
struct ContentView:View {
private struct AlertIdentifier: Identifiable {
var id: Choice
enum Choice {
case success
case failure
}
}
@State private var showAlert: AlertIdentifier? // init this as nil
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")))
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,在按钮中,我们将 设置为具有我们想要显示的警报类型showAlert的结构实例AlertIdentifier。在这种情况下,我们有两种类型:成功和失败(但我们可以拥有任意数量的类型,而且我们不需要使用名称success和failure)。设置后,它将显示适当的警报。
在 our 中,.alert(item:content:)我们切换不同的ids,以便我们可以确保为正确的选择显示正确的警报。
这种方法比拥有多个布尔值要容易得多,而且更容易扩展。
Sheets并且ActionSheets与Alerts它们的呈现方式非常相似。有四种呈现方式Sheets。
这两个需要Bool绑定:
.sheet(isPresented: Binding<Bool>, content: () -> View)
.sheet(isPresented: Binding<Bool>, onDismiss: (() -> Void)?, content: () -> Void)
Run Code Online (Sandbox Code Playgroud)
这两个需要Identifiable绑定:
.sheet(item: Binding<Identifiable?>, content: (Identifiable) -> View)
.sheet(item: Binding<Identifiable?>, onDismiss: (() -> Void)?, content: (Identifiable) -> View)
Run Code Online (Sandbox Code Playgroud)
因为ActionSheets有两种方式,比如Alerts.
使用Bool绑定:
.actionSheet(isPresented: Binding<Bool>, content: () -> ActionSheet)
Run Code Online (Sandbox Code Playgroud)
使用Identifiable绑定:
.actionSheet(item: Binding<Identifiable?>, content: (Identifiable) -> ActionSheet)
Run Code Online (Sandbox Code Playgroud)
如果您只需要显示一种类型的Alert,Sheet或者ActionSheet然后使用Bool绑定,则无需编写一些额外的代码行。
如果您要显示多种不同类型的Alerts、Sheets 或ActionSheets,请选择Identifiable绑定,因为它更易于管理。
可识别对象的更简单版本是使用枚举而不将其包装在结构中。在这种情况下,我们需要符合 Identifiable 因此我们需要一个计算属性来存储 id 值。我们还需要确保枚举使用 RawRepresentable 以便我们可以获得唯一的 id 值。我建议使用 Int 或 String。在下面的示例中,我使用的是 Int。
enum Choice: Int, Identifiable {
var id: Int {
rawValue
}
case success, failure
}
Run Code Online (Sandbox Code Playgroud)
然后在视图中我们可以执行以下操作:
struct ContentView:View {
enum Choice: Int, Identifiable {
var id: Int {
rawValue
}
case success, failure
}
@State private var showAlert: Choice? // init this as nil
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")))
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1810 次 |
| 最近记录: |