Gerbil Gerbil - 2 days ago 4
Swift Question

Swift: "Where" vs "If"

Is there any difference between these two syntaxes? If not, any benefit?

if let userName = userNameTextField.text where userName.characters.count > 0,
let password = passwordTextField.text where password.characters.count > 0,
let confirmation = confirmationTextField.text where confirmation == password
else {
return false
}


and:

if userNameTextField.text?.characters.count > 0 &&
passwordTextField.text?.characters.count > 0 &&
confirmationTextField.text == passwordTextField.text
{
return false
}


Answer

First of all, note that where clauses in optional binding conditions is deprecated in Swift 3.0, replaced by ,.

I.e.

let opt: Int?

/* Swift < 3 */
if let opt = opt where opt == 42 { /* ... */ }

/* Swift >= 3 */
if let opt = opt, opt == 42 { /* ... */ }

Secondly, your second example block wont compile in Swift >= 3.0, as the optional result from the optional chaining is not unwrapped; comparing optionals to literals has been removed in Swift 3.0 (thanks @MartinR), as per the following implemented proposals:

userNameTextField.text?.characters.count > 0 &&
/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   this is an optional that, for Swift >= 3.0, needs to be unwrapped 
   prior to comparing it to the integer literal */

Now, proceeding to answer your "is there any difference ..." question, assuming we look at your two options fixed for Swift 3.

  • You could choose to bind the value of the optional String property text of userNameTextField if you'd like to use it in the if block that follows, or
  • If youd only want to ascertain that the text property is not nil or empty (""), you could omit the binding in favour or simply checking its character.count

E.g.:

struct Foo {
    var bar: String?
}
var foo = Foo()

/* if you want to use foo.bar within the if block */
if let str = foo.bar, str.characters.count > 0 {
    // do something with str ...
    print(str)
}

/* if you only need to ascertain foo.bar is not nil
   and not empty */
if (foo.bar?.characters.count ?? 0) > 0 {
    // do something with str ...
    print("not empty")
}

If you simply want to ascertain the latter and return false in case the ascertation fails, you could prefer using a guard statement instead of if:

guard (foo.bar?.characters.count ?? 0) > 0 else { return false }
// ... if no false return, proceed with app flow here ...
Comments