-2

I'm building a very simple login verification app inside of xCode 7 using Swift. I'm extremely new to Swift and building apps in general, so I'm having some difficulty with a part of my code.

I'm checking whether or not a user has left any fields empty, and if they have, they will receive an error alert message.

However, when I go to build my project, I get the error:

Value of optional type 'String?' not unwrapped;

This is my code:

let userEmail = userEmailTextField.text
let userPassword = userPasswordTextField.text
let userRepeatPassword = repeatPasswordTextField.text

if(userEmail.isEmpty || userPassword.isEmpty || userRepeatPassword.isEmpty){
    displayAlertMessage("All fields are required.") // custom made function
    return;
}

Any help is appreciated.

Also, If someone could explain why my code is not functioning correctly, that would be awesome! Because, I can't seem to understand other forums explanations or fixes.

Julien Quere
  • 2,407
  • 16
  • 21
GROVER.
  • 4,071
  • 2
  • 19
  • 66
  • Three variables `userEmail`, `userPassword`, `userRepeatPassword` are not described in your post. I can make some guess, but it's better you add some descriptions about them. – OOPer Aug 28 '16 at 12:17
  • @OOPer sorry, I'll add them now – GROVER. Aug 28 '16 at 12:17
  • Lot's of options here: [How to check if a text field is empty or not in swift](http://stackoverflow.com/questions/24102641/how-to-check-if-a-text-field-is-empty-or-not-in-swift). – Martin R Aug 28 '16 at 12:19
  • You can find so many options searching with _value of optional type 'string?' not unwrapped_. But I would write the checking code using nil coalescing operator (`??`), like: `if((userEmail?.isEmpty ?? true) || (userPassword?.isEmpty ?? true) || (userRepeatPassword?.isEmpty ?? true)) {`. Better see other threads. – OOPer Aug 28 '16 at 12:29
  • @OOPer thanks for the comment. I'll test it out. – GROVER. Aug 28 '16 at 12:30
  • @OOPer yes, I did find some, however, because I am very new to Swift, I didn't quite understand most answers. – GROVER. Aug 28 '16 at 12:31
  • OK, I'll try to explain the code in my comment above as an answer. – OOPer Aug 28 '16 at 12:35
  • Done, but my answer cannot be the best solution for your issue. As you may need to use the non-Optional text values after you have checked all of them are non-empty. Please read again other solutions and find one best fit for your code. – OOPer Aug 28 '16 at 13:16

2 Answers2

2

The problem here is that the property text of UITextField is an optionl string so you have to change like this:

let userEmail = userEmailTextField.text!
let userPassword = userPasswordTextField.text!
let userRepeatPassword = repeatPasswordTextField.text!

or use it like this

guard let userEmail = userEmail, let userPassword = userPassword, let userRepeatPassword = userRepeatPassword where !userEmail.isEmpty && !userPassword.isEmpty && !userRepeatPassword.isEmpty else {
    displayAlertMessage("All fields are required.") // custom made function
    return;
}
Marco Santarossa
  • 4,058
  • 1
  • 29
  • 49
  • Would you mind explaining what that means? Or what the `!` marks do? :) thanks btw, this did indeed fix it! – GROVER. Aug 28 '16 at 12:26
  • @CaelanGrgurovic please check this swift guide: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html – Marco Santarossa Aug 28 '16 at 12:27
  • @CaelanGrgurovic If my answer fixes your problem please mark it as right, I would appreciate it, thank you – Marco Santarossa Aug 28 '16 at 12:28
  • oh wait never mind :/. It got rid of the error, however, on build and test, the application stopped and it told be the breakpoint was at the `if` statement. – GROVER. Aug 28 '16 at 12:29
  • i didn't understand the problem, can you send me a screenshot of the error? Anyway I replaced the if with the guard statement – Marco Santarossa Aug 28 '16 at 12:30
1

As already noted, UITextFields property text is of type String? (aka Optional<String>), so you cannot directly apply methods or get properties of String.

Forced unwrapping (!) would be very risky, as that property may actually be nil.

In such cases, you have some options to treat the Optional value:

  • Use optional bindings, its representative is if let, but guard let or sometimes while let may be useful.
  • Use optional chaining, represented with ?.. Maybe you are using this somewhere else.
  • Giving default value using nil-coalescing operator ??.

With the latter two, I get this line:

if((userEmail?.isEmpty ?? true) || (userPassword?.isEmpty ?? true) || (userRepeatPassword?.isEmpty ?? true)) {

As you see, userEmails type is String?, so I have chosen optional chaining:

userEmail?.isEmpty

Which may return three kinds of values:

  • Optional.Some(true)
  • Optional.Some(false)
  • Optional.None (this is called nil)

(I omitted specifying <Bool>, for readability.)


It's still Optional, so I added ?? true to supply a default value for nil case.

userEmail?.isEmpty ?? true
  • lhs:Optional.Some(true) -> true (left hand side of ?? is not nil, use lhs value unwrapped)
  • lhs:Optional.Some(false) -> false (left hand side of ?? is not nil, use lhs value unwrapped)
  • lhs:Optional.None -> true (left hand side of ?? is nil, so right hand side value is used)

You know, when the text is nil, you should think it as empty, so supplying default value true for nil case is appropriate.

You need to write similar code for all three variables, and you get the line I have shown above.

OOPer
  • 47,149
  • 6
  • 107
  • 142