0

Given a non-optional value, how can I match against an optional in a switch statement?

For example:

let test = "some string"

let x: String? = nil
let y: String? = "some string"
let z: String? = "another string"

switch test {
case x:
    print(x)
case y:
    print(y)
case z:
    print(z)
default: break
}

results in:

Expression pattern of type 'String?' cannot match values of type 'String'

for each case...

I've read the swift docs on patterns and switch but I can't seem to find a way of making this work.

I know I can work around this, but there must be a way of making this work...

Edit

As requested, here is my actual use case. Note all text fields are optional...

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        // TODO: Replace with switch if possible

//        switch textField {
//        case nameTextField:
//            usernameTextField?.becomeFirstResponder()
//        case usernameTextField:
//            dateOfBirthTextField?.becomeFirstResponder()
//        case dateOfBirthTextField:
//            phoneTextField?.becomeFirstResponder()
//        case phoneTextField:
//            phoneTextField?.resignFirstResponder()
//        default: break
//        }

        if textField == nameTextField {
            usernameTextField?.becomeFirstResponder()
        } else if textField == usernameTextField {
            dateOfBirthTextField?.becomeFirstResponder()
        } else if textField == dateOfBirthTextField {
            phoneTextField?.becomeFirstResponder()
        } else if textField == phoneTextField {
            phoneTextField?.resignFirstResponder()
        }
        return false
    }
2
  • For me this is actually too general a question. You have to be facing something more specific - something less "theoretical". Could you post that code? Commented Oct 28, 2017 at 4:09
  • @dfd See update. Commented Oct 28, 2017 at 4:15

2 Answers 2

2

Swift 4.0

You can check with optional case as like below. Hope this will help you.

let test = "some string"

let x: String? = nil
let y: String? = "some string"
let z: String? = "another string"

switch test {
case let val where val == x:
    print(x)
case let val where val == y:
    print(y)
case let val where val == z:
    print(z)
default:
    break
}
Sign up to request clarification or add additional context in comments.

Comments

1

For your actual use-case: I would create an array of all non-nil text fields. Then you can lookup the current text field in that array and make the next one in the list the first responder:

let fields = [nameTextField, usernameTextField, dateOfBirthTextField, phoneTextField]
    .flatMap { $0 }
if let idx = fields.index(of: textField), idx + 1 < fields.count {
    fields[idx + 1].becomeFirstResponder()
} else {
    textField.resignFirstResponder()
}

This is less error-prone and can easily be modified if the number or order of the text fields changes.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.