0

I've a simple Login app. enter username and password and click login button, i will get response from server which contains a Bool. if the Bool is true then go to next page, else show an Alert with error message.

struct ContentView : View {

@State var username: String = ""
@State var password: String = ""

@ObjectBinding var loginVM : LoginViewModel = LoginViewModel()

var body: some View {

NavigationView {
            VStack {

  TextField($username, placeholder: Text("Username")
  TextField($password, placeholder: Text("Password")

Button(action: {

                    let params : [String:String] =
                        ["username":self.username,
                         "password":self.password]

                    self.loginVM.doLogin(params:params)

                }) {
                    Text("Login")
                }
                .alert(isPresented: $loginVM.isLogin) {
                    Alert(title: Text("Login Error"), message: 
                  Text(loginVM.errorMessage), 
                  dismissButton: .default(Text("Ok")))
                }
}
}

}
//LoginViewModel:

class LoginViewModel : BindableObject  {

let willChange = PassthroughSubject<Void,Never>()

    var isLogin : Bool = false { willSet { willChange.send() } }
    var errorMessage = "" { willSet { willChange.send() } }

func doLogin(params:[String:String]) {

        Webservice().login(params: params) { response in

            if let myresponse = response {

                if myresponse.login {

                   self.isLogin = true // this will fire willChange.send()
                   self.errorMessage = ""

                 } else {
                  self.isLogin = false
                  self.errorMessage = myresponse.errorMessage
                 }
    }
}
}

//and my login response is:

{ "login" : true, "error": "" } OR { "login" : false, "error": "Password Incorrect"}

THE PROBLEM IS: if login is TRUE (in the response)then -> in the ContentView '$loginVM.isLogin' becomes TRUE and Alert will Show. if login is FALSE then -> $loginVM.isLogin becomes FALSE and Alert will Not Show. I just want the OPPOSITE to happen. Means i want to show the alert only if the login is FALSE. Also If the login is true, I want to go to next page(how to do that?), else show the errorMessage in the Alert.

Sreeni
  • 205
  • 2
  • 6
  • I can partially help you. Earlier today I posted an answer (with an associated repo) of setting up a model, making it an `@EnvironmentObject` and passing it to a presented sheet. at the very least it should help you to retrieve `LoginViewModel` values in your alert: https://stackoverflow.com/questions/57148220/swiftui-present-alert-with-input-field?noredirect=1#comment100838791_57148220 –  Jul 23 '19 at 12:47

1 Answers1

0

Let's see :

You could add an additional property to your view model called isError - and make it true when there is an error condition in your model:

 .alert(isPresented: $loginVM.isError) { ... }

Showing different things if loginVM.isLogin is true or false is even simpler:

  if loginVM.isLogin {
    // Showing the appropriate content for a logged in user
    Text("Login succesful")

  } else {
    // showing the login form
    TextField($username, placeholder: Text("Username")
    TextField($password, placeholder: Text("Password")

    Button(...)
  }
Bogdan Farca
  • 3,856
  • 26
  • 38
  • so i don't need separate views for Login and Home page right? ok that's cool. So Next i need to store the Login details (ie LoginVM EnvironmentObject) to UserDefaults, so that i could fetch it when app launches next time ? – Sreeni Jul 24 '19 at 06:46
  • Sure, if you want to persist the login details somewhere, UserDefaults is possible option, of course. – Bogdan Farca Jul 24 '19 at 07:47