SwiftUI-在按下和导航按钮时显示错误消息的表单

时间:2019-08-25 11:17:15

标签: swift swiftui

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

我尝试通过使用字段值并在按下按钮时检查是否为空来有条件地显示错误消息,但是,我不知道如何导航到下一个屏幕。

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

3 个答案:

答案 0 :(得分:1)

感谢部分答案here,下面是一些有效的代码。

首先,我将所有内容移至EnvronmentObject中,以使事情更容易传递给您的第二个视图。我还添加了 second 切换变量:

class Model: ObservableObject {
    @Published var fieldValue = ""
    @Published var showErrorMessage = false
    @Published var showSecondView = false
}

接下来,在ContentView中更改两件事。我添加了一个隐藏的NavigationLink(带有一个isActive参数)来实际触发推送,并更改了Button动作以执行本地功能:

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将带您进入下一个视图。

最后,第二个视图:

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),您将再次发送回第二个视图。

您没有在第二个视图内容上发布任何详细信息,因此我自由地将someText添加到模型中,向您展示如何使用EnvironmentObject轻松地将内容传递给模型。 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

答案 1 :(得分:1)

另一种方法是,当fieldValue为空时,有条件地使“ Next”按钮成为Button,而当fieldValue有效时,使NavigationLink为条件。 Button的情况将触发您的错误消息视图,NavigationLink将为您进行导航。保持这一点接近您的样本,以下似乎可以解决问题。

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import { subscribe } from 'redux'
import { store } from './Redux/store'
import { Provider } from 'react-redux'

let rerender = (store) => {
   ReactDOM.render(
      <Provider store={store}>
         <App />
      </Provider>,
      document.getElementById('root'))
}

rerender(store)

store.subscribe(() => {
   rerender(store)
})

答案 2 :(得分:0)

通过使用此代码,我们可以在字段为else时显示警报。它将导航。

struct SomeView: View {

    @State var userName = ""
    @State var password = ""
    @State var showErrorMessage = false

    var body: some View {
        NavigationView {
            VStack {
                TextField("Enter Username", text: $userName).textFieldStyle(RoundedBorderTextFieldStyle())
                SecureField("Enter Your Password", text: $password)
                    .textFieldStyle(RoundedBorderTextFieldStyle())


                if userName == "" || password == "" {
                    Button(action: {
                        if self.userName == ""  || self.password == "" {
                            self.showErrorMessage = true
                        }
                   }, label: {
                        Text("Login")
                    })
                } else {
                    // move case
                    NavigationLink("Login", destination: Text("Login successful"))
                }
            }.alert(isPresented: $showErrorMessage) { () -> Alert in
                Alert(title: Text("Important Message"), message: Text("Please Fill all the Fields"), primaryButton: .default(Text("Ok")), secondaryButton: .destructive(Text("Cancel")))
            }
        }
    }
}