当内容为 nil 时,Swift 保护语句不会返回

Posted

技术标签:

【中文标题】当内容为 nil 时,Swift 保护语句不会返回【英文标题】:Swift guard statement doesn't return when content is nil 【发布时间】:2020-02-19 21:36:02 【问题描述】:

我正在编写用于注册和注册用户视图的代码。它应该在运行更多代码之前检查文本字段是否为零。

guard let a = b else/* b 为 nil 时的代码*/return

我知道如果 b 为 nil,guard 语句应该返回 在我的编码中 b 是 nil 但是它没有返回不确定原因。我还打印出它对我来说看起来像 nil 的内容。谢谢

这里是代码

类 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 pas-s-record = userrecord?.first?.userPass

    if (email == emailrecord && password == pas-s-record)
        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"


【问题讨论】:

你怎么知道它不会返回?按下按钮时应用程序是否冻结? 你可能会混淆 nil 和空字符串。试试guard let a = textField.text, !a.isEmpty else .... 我把 print 放在代码中,守卫之后它应该只在它有价值的情况下运行。它仍然打印(代码在 do catch) 我在你的代码中看到了很多守卫。你指的是哪一个?在您的第一个守卫中,您将email: String?String? 进行比较 @OOPer 你是对的。我看到 UITextField 的定义它说默认值为 nil。但是,当我查看 text 的定义时,它说 string 默认为 @" "。这是否意味着它永远不会为零? 【参考方案1】:

您可能错误地使用了该模式。您应该使用guard let ... 来测试非零值。

如果你有财产

var email: String? // nil

然后

guard email == emailtextfile!.text ... 如果两个字符串都为零,则将通过。

要测试两个字符串都不为零,并且它等于您的变量,您应该使用

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
...

如果您要测试非零、非空字符串,请按照问题中 cmets 中的建议尝试 guard let email = ..., !email.isEmpty ... else ...

还请注意,无需强制展开您的文本字段。 emailTextField?.text 可以。

仅查看 API,UITextfield.text 默认为 @"",它在 Swift 中桥接为空字符串。

【讨论】:

我尝试了 guard let a = textField.text, !a.isEmpty else ....,然后它返回了。我认为它有一个空字符串而不是 nil。 听起来很可能。 textfield 的 text 属性在 swift 中变为可选,因为它不是非空值,但如果没有显式设置为 nil,它可能具有空值。我不会依赖这种行为。最好先测试是否为 nil,然后再测试是否为空。 为了清楚起见,修改了我的回复。 text 属性默认有@"",这绝对符合您描述的行为。 如果它从不为零,我如何检测它是否为空 只要guard let email = textfield.text, !email.isEmpty。默认情况下它被记录为@"",但它仍然是可选的,即它仍然可以设置为nil。【参考方案2】:

如果某些先决条件失败,则使用Guard 提前退出。在您的情况下,如果用户在电子邮件和密码字段中输入了某些内容,您需要通过该保护,因此在您的 loginButton 操作中,您需要更新您的代码,例如:

@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"
    

我在那里更新的是将可选文本解包为非可选局部变量电子邮件和密码,并将比较运算符更新为分配运算符。 希望这会对您有所帮助,并且您再也不会在那里崩溃了。

【讨论】:

【参考方案3】:

如果“电子邮件”变量 vas 声明为全局的简单解决方案:

guard (self.email != nil) else  return 

【讨论】:

以上是关于当内容为 nil 时,Swift 保护语句不会返回的主要内容,如果未能解决你的问题,请参考以下文章

Swift 3:当孩子存在时,FirebaseDB 返回 nil

Ruby - 失败语句/保护条件返回 nil

Swift的可选链,类型转换和扩展

Swift 在一行中返回关联的枚举值或 nil

Swift 4 Capture Photo,photoOutput 返回 nil

Swift 懒加载