Swift: тестирование опционального значения в корпусе коммутатора

В Swift, как я могу написать случай в инструкции switch, которая проверяет значение, которое переключается на содержимое опционального, пропуская регистр, если опция содержит nil?

Вот как я могу себе представить, что это может выглядеть:

let someValue = 5
let someOptional: Int? = nil

switch someValue {
case someOptional:
    // someOptional is non-nil, and someValue equals the unwrapped contents of someOptional
default:
    // either, someOptional is nil, or someOptional is non-nil but someValue does not equal the unwrapped contents of someOptional
}

Если я просто напишу это точно так, компилятор жалуется, что someOptional не разворачивается, но если я явным образом развожу его, добавив ! в конец, я, конечно же, получу ошибку времени выполнения someOptional содержит nil. Добавление ? вместо ! мне показалось бы (в духе необязательной цепочки, я полагаю), но не исключает ошибки компилятора (т.е. Фактически не разворачивает необязательный).

Ответ 1

Необязательно это просто enum вот так:

enum Optional<T> : Reflectable, NilLiteralConvertible {
    case None
    case Some(T)

    // ...
}

Таким образом, вы можете сопоставлять их как обычно "Соответствующие значения" с шаблонами соответствия:

let someValue = 5
let someOptional: Int? = nil

switch someOptional {
case .Some(someValue):
    println("the value is \(someValue)")
case .Some(let val):
    println("the value is \(val)")
default:
    println("nil")
}

Если вы хотите совпадения из someValue, используйте защитное выражение:

switch someValue {
case let val where val == someOptional:
    println(someValue)
default:
    break
}

А для Swift> 2.0

switch someValue {
case let val where val == someOptional:
    print("matched")
default:
    print("didn't match; default")        
}

Ответ 2

Начиная с Xcode 7 (из примечаний к выпуску бета-версии 1), "новый шаблон x? может использоваться для сопоставления с дополнительными параметрами в качестве синонима для .Some(x)". Это означает, что в Xcode 7 и более поздних версиях также будет работать следующий вариант ответа rintaro :

let knownValue = 5

switch someOptional {
case knownValue?:
    // Contents of someOptional are knownValue, defined above.
case let otherValue?:
    // Contents of someOptional are *any* non-nil value not already tested for.
    // Unwrapped contents are assigned to otherValue for use inside this case.
default:
    // someOptional is nil.
}

Ответ 3

В Swift 4 вы можете использовать Необязательно: ExpressibleByNilLiteral Apple для переноса необязательного

https://developer.apple.com/documentation/swift/optional

Пример

enum MyEnum {
    case normal
    case cool
}

некоторые

let myOptional: MyEnum? = MyEnum.normal

switch smyOptional {
    case .some(.normal): 
    // Found .normal enum
    break

    case .none: 
    break

    default:
    break
}
не

ни

let myOptional: MyEnum? = nil

switch smyOptional {
    case .some(.normal): 
    break

    case .none: 
    // Found nil
    break

    default:
    break
}

по умолчанию

let myOptional: MyEnum? = MyEnum.cool

switch smyOptional {
    case .some(.normal): 
    break

    case .none: 
    break

    default:
    // Found .Cool enum
    break
}

Перечисление со значением

enum MyEnum {
    case normal(myValue: String)
    case cool
}

некоторая ценность

let myOptional: MyEnum? = MyEnum.normal("BlaBla")

switch smyOptional {
case .some(.normal(let myValue)) where myValue == "BlaBla":
    // Here because where find in my myValue "BlaBla"
    break

// Example for get value
case .some(.normal(let myValue)):
    break

// Example for just know if is normal case enum
case .some(.normal):
    break

case .none:
    break

default:

    break
}