2014-11-15 4 views
62

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

Вот как я себе это может выглядеть:

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. Добавление ? вместо ! имеет смысл для меня (в духе необязательной цепочки, я полагаю), но не исключает ошибки компилятора (т. Е. Фактически не разворачивает необязательный).

ответ

80

Дополнительно просто enum так:

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

    // ... 
} 

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

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, используя guard expression:

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")   
} 
+0

Обратите внимание, что в Swift 3, некоторые/ни один из них в нижнем регистре, то есть вы будете использовать .some вместо .some – Adam

26

По состоянию Xcode 7 (от примечания к выпуску беты-1), «новый образец x? может быть использован для сопоставления с образцом против опций как синоним .Some(x)». Это означает, что в Xcode 7, а затем следующее изменение rintaro's answer будет работать также:

switch someOptional { 
case someValue?: 
    print("the value is \(someValue)") 
case let val?: 
    print("the value is \(val)") 
default: 
    print("nil") 
} 
+2

Речь идет о сопоставляя необязательное значение с необязательным, этот ответ наоборот. –

+2

Правда, однако этот ответ был первоначально написан OP как обновление вопроса, поэтому для него это было неопровержимо жизнеспособное решение; Я просто переместил его в ответ на wiki сообщества. Возможно, @GeorgeWS может уточнить, почему смена switch & case args работает для его прецедента? –

+0

Я немного потерян. какая разница между вашими первыми двумя случаями? 'someValue?' - это какое-то другое определенное значение, но 'case let val?' - это просто безопасная развернутая версия 'someOptional' ?! – Honey

Смежные вопросы