0
votes

I am writing the code for sign up and register user view. it should check if textfield is nil before it run more code.

guard let a = b else{/* code when b is nil*/return}

I know guard statement should return if b is nil In my coding b is nil however it didn't return not sure why. Also I printout the content it does look like nil to me. Thank you

Here is the coding

class userLoginView: UIViewController {

let realm = try! Realm()
var email:String?
var password:String?
var userResult:Results<userInfo>?
var logedin:Bool = false

@IBOutlet weak var emailtextfile: UITextField!
@IBOutlet weak var passwordtextfile: UITextField!
@IBOutlet weak var errorMessage: UILabel!

@IBOutlet weak var fnametext: UITextField!
@IBOutlet weak var lnametext: UITextField!
@IBOutlet weak var emailsigntext: UITextField!
@IBOutlet weak var signpasstext: UITextField!
@IBOutlet weak var passagaintext: UITextField!
@IBOutlet weak var contractortext: UITextField? = nil
@IBOutlet weak var signError: UILabel!

@IBAction func loginButton(_ sender: Any) {

    guard email == emailtextfile!.text,
        password == passwordtextfile!.text else{
            errorMessage?.text = "Please fill in your email and password"
            return
    }
    if checkUser(_email: email ?? "", _pass: password ?? "" ){
        logedin = true
        if let adminView = self.storyboard?.instantiateViewController(withIdentifier: "adminView") as? adminviewController{
            self.navigationController?.pushViewController(adminView, animated: true)
            UserDefaults.standard.set(email, forKey: "email")
            UserDefaults.standard.set(password, forKey: "password")

        }
    }else{
        errorMessage?.text = "Email or Password doesn't match our record"
    }
}

@IBAction func signupsegues(_ sender: UIButton!) {
    if let signupview =  storyboard?.instantiateViewController(withIdentifier: "signupView"){
            navigationController?.pushViewController(signupview, animated: true)
        }
}




@IBAction func signmeup(_ sender: UIButton!) {

    let contractor = contractortext?.text ?? ""
    guard let email = emailsigntext.text else{
        signError?.text = "Please fill in email"
        return}
    guard let fname = fnametext.text else{
        signError?.text = "Please fill in first name"
        return}
    guard let lname = lnametext.text else{
        signError?.text = "Please fill in last name"
        return}
    guard let pass = signpasstext.text else{
        signError?.text = "Please fill password"
        return}
    guard let passagain = passagaintext.text else{
        signError?.text = "Please fill confirm password"
            return
    }

    do{
        print("pass:" + pass)
        print("passagain" + passagain)
        print("email:" + email)
        print("fname:" + fname)
        print("lname:" + lname)


    try signupUser(_email: email, _firstname: fname, _lastName: lname, _password: pass, _comfirmpass: passagain, _contractor: contractor)
    }catch{
        print("some error")
    }
}

@IBAction func forgotButton(_ sender: Any) {
}

override func viewDidLoad() {
    super.viewDidLoad()

    userResult = realm.objects(userInfo.self)

}
override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}
func checkUser(_email:String, _pass:String) -> Bool {
    var checked:Bool = false
    let userrecord = userResult?.filter("userEmail = %@", email!)
    let emailrecord = userrecord?.first?.userEmail
    let passrecord = userrecord?.first?.userPass

    if (email == emailrecord && password == passrecord){
        checked = true
    }else {checked = false}
    return checked
}

func signupUser(_email:String!,_firstname:String!,_lastName:String!,_password:String!,_comfirmpass:String!,_contractor:String?) throws ->Void {

    if _password.elementsEqual(_comfirmpass) {
        let temp = userInfo(value: [_email!,_password!,_firstname!,_lastName!,_contractor ?? "",false])

        try realm.write {
                realm.add(temp)
        }
    }else{
        signError?.text = "password does not match"}

}

}

3
How do you know it doesn't return? Does the app freeze when you press the button? - kid_x
You may be confused with nil and empty String. Try guard let a = textField.text, !a.isEmpty else {....}. - OOPer
I put print in the code after guard which it should only run if it has value. it still printed (code in do catch) - Liu Angie
I see a lot of guards in your code. Which one are you referring to? In your first guard, you are comparing email: String? with a String? - kid_x
@OOPer you are right. I saw definition of UITextField it says default value is nil. However, when I look at the definition of text it says string is @" "by default. Is that mean it will never be nil? - Liu Angie

3 Answers

1
votes

You may be using the pattern incorrectly. You should be using guard let ... to test for non-nil values.

If you have a property

var email: String? // nil

then

guard email == emailtextfile!.text ... will pass if both strings are nil.

To test that both the string is not nil, and that it is equal to your variable, you should be using

guard let email = emailTextFile?.text, self.email == email, ... else {
    // stuff if email is nil
    return 
}
// stuff to do if email has a value and is equal to the value in the textfield
...

If you're testing for non-nil, non-empty strings, try guard let email = ..., !email.isEmpty ... else { ... } as suggested in the comments in your question.

Also note there is no need to force-unwrap your textfield. emailTextField?.text will do.

Just looking at the API, UITextfield.text is @"" by default, which bridges to an empty string in Swift.

0
votes

Guard is used for early exit if some pre-conditions fail. And in your case you need to pass that guard if the user has entered something in email and password fields, so in your loginButton action you need to update your code like:

@IBAction func loginButton(_ sender: Any) {
    guard let email = emailtextfile.text, email.count > 0,
        let password = passwordtextfile.text, password.count > 0 else {
        errorMessage?.text = "Please fill in your email and password"
        return
    }
    if checkUser(_email: email, _pass: password ) {
        logedin = true
        if let adminView = self.storyboard?.instantiateViewController(withIdentifier: "adminView") as? adminviewController {
            self.navigationController?.pushViewController(adminView, animated: true)
            UserDefaults.standard.set(email, forKey: "email")
            UserDefaults.standard.set(password, forKey: "password")

        }
    } else {
        errorMessage?.text = "Email or Password doesn't match our record"
    }
}

What I have updated there is to unwrap the optional texts to non-optional local variables email and password And update the comparison operator to assigning operator. Hope this will help you and you never get a crash there again.

-1
votes

Simple solution if the "email" variable vas declared as global:

guard (self.email != nil) else { return }