SwiftUI - 按下按钮和导航时带有错误消息的表单 [英] SwiftUI - Form with error message on button press and navigation
问题描述
我有以下场景.我有一个文本字段和一个按钮,我需要的是在该字段为空的情况下显示错误消息,如果不是,则将用户导航到下一个屏幕.
I have the following scenario. I have a text field and a button, what I would need is to show an error message in case the field is empty and if not, navigate the user to the next screen.
我尝试通过使用字段值并在按下按钮时检查它是否为空来有条件地显示错误消息,但是,我不知道如何导航到下一个屏幕.
I have tried showing the error message conditionally by using the field value and checking if it is empty on button press, but then, I don't know how to navigate to the next screen.
struct SomeView: View {
@State var fieldValue = ""
@State var showErrorMessage = false
var body: some View {
NavigationView {
VStack {
TextField("My Field", text: $fieldValue).textFieldStyle(RoundedBorderTextFieldStyle())
if showErrorMessage {
Text("Error, please enter value")
}
Button(action: {
if self.fieldValue.isEmpty {
self.showErrorMessage = true
} else {
self.showErrorMessage = false
//How do I put navigation here, navigation link does not work, if I tap, nothing happens
}
}) {
Text("Next")
}
}
}
}
}
使用 UIKit 会很容易,因为我可以使用 self.navigationController.pushViewController
Using UIKit would be easy since I could use self.navigationController.pushViewController
推荐答案
感谢部分答案此处,这是一些工作代码.
Thanks to part of an answer here, here's some working code.
首先,我将所有内容都移到了 EnvronmentObject
中,以便更轻松地将内容传递给您的第二个视图.我还添加了一个 second 切换变量:
First, I moved everything into an EnvronmentObject
to make things easier to pass to your second view. I also added a second toggle variable:
class Model: ObservableObject {
@Published var fieldValue = ""
@Published var showErrorMessage = false
@Published var showSecondView = false
}
接下来,在您的 ContentView
中更改两件事.我添加了一个隐藏的 NavigationLink
(带有一个 isActive
参数)来实际触发推送,同时更改您的 Button
操作以执行本地函数:
Next, change two things in your ContentView
. I added a hidden NavigationLink
(with a isActive
parameter) to actually trigger the push, along with changing your Button
action to execute a local function:
struct ContentView: View {
@EnvironmentObject var model: Model
var body: some View {
NavigationView {
VStack {
TextField("My Field", text: $model.fieldValue).textFieldStyle(RoundedBorderTextFieldStyle())
NavigationLink(destination: SecondView(), isActive: $model.showSecondView) {
Text("NavLink")
}.hidden()
Button(action: {
self.checkForText()
}) {
Text("Next")
}
.alert(isPresented: self.$model.showErrorMessage) {
Alert(title: Text("Error"), message: Text("Please enter some text!"), dismissButton: .default(Text("OK")))
}
}
}
}
func checkForText() {
if model.fieldValue.isEmpty {
model.showErrorMessage.toggle()
} else {
model.showSecondView.toggle()
}
}
}
切换 showErrorMessage
将显示 Alert
并切换 `showSecondView 将带您到下一个视图.
Toggling showErrorMessage
will show the Alert
and toggling `showSecondView will take you to the next view.
最后,第二个观点:
struct SecondView: View {
@EnvironmentObject var model: Model
var body: some View {
ZStack {
Rectangle().fill(Color.green)
// workaround
.navigationBarBackButtonHidden(true) // not needed, but just in case
.navigationBarItems(leading: MyBackButton(label: "Back!") {
self.model.showSecondView = false
})
Text(model.fieldValue)
}
}
func popSecondView() {
model.showSecondView.toggle()
}
}
struct MyBackButton: View {
let label: String
let closure: () -> ()
var body: some View {
Button(action: { self.closure() }) {
HStack {
Image(systemName: "chevron.left")
Text(label)
}
}
}
}
这是上面链接的答案对我有帮助的地方.似乎在 beta 6 中仍然存在导航返回的错误.如果没有这种解决方法(切换 showSecondView
),您将再次被发送回第二个视图.
This is where the above linked answer helped me. It appears there's a bug in navigation back that still exists in beta 6. Without this workaround (that toggles showSecondView
) you will get sent back to the second view one more time.
您没有发布有关第二个视图内容的任何详细信息,因此我冒昧地将 someText
添加到模型中,以向您展示如何使用 环境对象
.在 SceneDelegate
中需要进行一些设置:
You didn't post any details on the second view contents, so I took the liberty to add someText
into the model to show you how to easily pass things into it can be using an EnvironmentObject
. There is one bit of setup needed to do this in SceneDelegate
:
var window: UIWindow?
var model = Model()
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let contentView = ContentView()
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView.environmentObject(model))
self.window = window
window.makeKeyAndVisible()
}
}
我注意到这方面的细微变化,具体取决于您的项目的创建时间(beta 6 声明了一个 contentView
实例,而旧版本则没有).无论哪种方式,声明一个 model
的实例,然后将 envoronmentObject
修饰符添加到 contentView
.
I noticed a slight change in this, depending on when your project was created (beta 6 declares an instance of contentView
where older versions do not). Either way, declare an instance of model
and then add the envoronmentObject
modifier to contentView
.
这篇关于SwiftUI - 按下按钮和导航时带有错误消息的表单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!