Проверка значения типа bool, необязательный
когда я хочу проверить, является ли необязательный Bool истинным, это не работает:
var boolean : Bool? = false
if boolean{
}
Это приводит к такой ошибке:
дополнительный тип ' @IvalueBool?'не может использоваться как логическое значение; тест для '!= ноль'
вместо этого
Я не хочу проверять на ноль; я хочу проверить, если возвращенное значение true.
Я всегда должен делать if boolean == true если я работаю с дополнительным Bool?
Так как опционные не соответствуют BooleanType больше, разве компилятор не должен знать, что я хочу проверить значение Bool?
3 ответов:
С дополнительными логическими значениями необходимо сделать проверку явной:
if boolean == true { ... }в противном случае вы можете развернуть дополнительно:
if boolean! { ... }но это создает исключение времени выполнения, если boolean
nil- чтобы не допустить этого:if boolean != nil && boolean! { ... }до бета-версии 5 это было возможно, но он был изменен, как сообщается в примечаниях к выпуску:
Optionals больше не будут неявно оцениваться как true, когда они имеют значение, и false, когда они этого не делают, чтобы избегайте путаницы при работе с необязательными значениями Bool. Вместо явной проверки в отношении Нилова с == или != операторы, чтобы узнать, содержит ли необязательное значение.
добавление: как предложил @MartinR, более компактное изменение к 3-му варианту использует оператор коалесценции:
if boolean ?? false { // this code runs only if boolean == true }что означает: если boolean не равно nil, выражение вычисляется до логического значения (т. е. с использованием развернутого логического значения), в противном случае выражение вычисляется к
false
дополнительные привязки
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и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оператор, полезно определить общий подход, будь то проверка на истинность, ложь или объединение развернутого значения с другими выражениями.по мере усложнения выражения, Я нахожу необязательный привязывающий подход более гибким и более понятным, чем другие подходы. Обратите внимание, что необязательная привязка работает с любым необязательным типом (
Int?,String?и т. д.).
Я нашел другое решение, перегружая булевы операторы. Например:
public func < <T: Comparable> (left: T?, right: T) -> Bool { if let left = left { return left < right } return false }Это может быть не совсем в "духе" языковых изменений, но это позволяет безопасно разворачивать опциональные значения, и это можно использовать для условных обозначений в любом месте, включая циклы while.
Comments