SwiftUI - 按下按钮和导航时带有错误消息的表单 [英] SwiftUI - Form with error message on button press and navigation

查看:27
本文介绍了SwiftUI - 按下按钮和导航时带有错误消息的表单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下场景.我有一个文本字段和一个按钮,我需要的是在该字段为空的情况下显示错误消息,如果不是,则将用户导航到下一个屏幕.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆