Проверка значения дополнительного Bool
Когда я хочу проверить, является ли опциональный Bool истинным, выполнение этого не работает:
var boolean : Bool? = false
if boolean{
}
Это приводит к ошибке:
Дополнительный тип '@IvalueBool?' не может использоваться как логическое; тест для '!= nil' вместо
Я не хочу проверять нуль; Я хочу проверить, вернётся ли значение.
Должен ли я всегда делать if boolean == true
, если я работаю с дополнительным Bool?
Так как опции не соответствуют BooleanType
, не должен ли компилятор знать, что я хочу проверить значение Bool?
Ответы
Ответ 1
С дополнительными логическими значениями необходимо сделать чек явным:
if boolean == true {
...
}
В противном случае вы можете распаковать опцию:
if boolean! {
...
}
Но это генерирует исключение во время выполнения, если boolean nil
- для предотвращения этого:
if boolean != nil && boolean! {
...
}
До бета-версии 5 это было возможно, но оно было изменено, как указано в примечаниях к выпуску:
Опционы уже неявно оценивают значение true, когда они имеют значение и false, когда они этого не делают, во избежание путаницы при работе с дополнительными значениями Bool. Вместо этого сделайте явную проверку против nil с операторами == или! =, Чтобы узнать, содержит ли опциональное значение значение.
Приложение: как предложено @MartinR, более компактным вариантом третьего варианта является использование оператора коалесценции:
if boolean ?? false {
...
}
что означает: если boolean не равен nil, выражение оценивается по логическому значению (т.е. с использованием развернутого логического значения), в противном случае выражение оценивается как false
Ответ 2
Дополнительная привязка
Swift 3 и 4
var booleanValue : Bool? = false
if let booleanValue = booleanValue, booleanValue {
// Executes when booleanValue is not nil and true
// A new constant "booleanValue: Bool" is defined and set
print("bound booleanValue: '\(booleanValue)'")
}
Swift 2.2
var booleanValue : Bool? = false
if let booleanValue = booleanValue where booleanValue {
// Executes when booleanValue is not nil and true
// A new constant "booleanValue: Bool" is defined and set
print("bound booleanValue: '\(booleanValue)'")
}
Код let booleanValue = booleanValue
возвращает false
, если booleanValue
is nil
и блок if
не выполняется. Если booleanValue
не nil
, этот код определяет новую переменную с именем booleanValue
типа Bool
(вместо необязательной, Bool?
).
Код Swift 3 и 4 booleanValue
(и код Swift 2.2 where booleanValue
) оценивает новую переменную booleanValue: Bool
. Если это правда, блок if
выполняется с помощью новой переменной booleanValue: Bool
в области видимости (позволяющей опции ссылаться на связанное значение снова в блоке if
).
Примечание. Это соглашение Swift для обозначения связанной константы/переменной так же, как и необязательная константа/переменная, например let booleanValue = booleanValue
. Этот метод называется переменным затенением. Вы можете отказаться от соглашения и использовать что-то вроде let unwrappedBooleanValue = booleanValue, unwrappedBooleanValue
. Я указываю это, чтобы понять, что происходит. Я рекомендую использовать переменную затенение.
Другие подходы
Ниль-коалесцирующий
Ниль-коалесцирование ясно для этого конкретного случая
var booleanValue : Bool? = false
if booleanValue ?? false {
// executes when booleanValue is true
print("optional booleanValue: '\(booleanValue)'")
}
Проверка на false
не такая прозрачная
var booleanValue : Bool? = false
if !(booleanValue ?? false) {
// executes when booleanValue is false
print("optional booleanValue: '\(booleanValue)'")
}
Примечание: if !booleanValue ?? false
не компилируется.
Принудительное форматирование необязательно (избегать)
Принудительное развертывание увеличивает вероятность того, что кто-то внесет изменения в будущее, которое компилируется, но сбой во время выполнения. Поэтому я бы избегал чего-то вроде этого:
var booleanValue : Bool? = false
if booleanValue != nil && booleanValue! {
// executes when booleanValue is true
print("optional booleanValue: '\(booleanValue)'")
}
Общий подход
Хотя этот вопрос задает вопрос, как проверить, является ли Bool?
true
в инструкции if
, полезно определить общий подход, проверяя ли true, false или объединяете разворачиваемое значение с другими выражениями.
По мере того, как выражение становится более сложным, я нахожу дополнительный способ привязки более гибким и понятным, чем другие подходы. Обратите внимание, что необязательное связывание работает с любым необязательным типом (Int?
, String?
и т.д.).
Ответ 3
Я нашел другое решение, перегружая булевы операторы. Например:
public func < <T: Comparable> (left: T?, right: T) -> Bool {
if let left = left {
return left < right
}
return false
}
Это может быть не полностью в "духе" изменений языка, но оно позволяет безопасно разворачивать дополнительные опции и может использоваться для условий в любом месте, в том числе в циклах.