Проверка значения типа bool, необязательный



когда я хочу проверить, является ли необязательный Bool истинным, это не работает:



var boolean : Bool? = false
if boolean{
}


Это приводит к такой ошибке:




дополнительный тип ' @IvalueBool?'не может использоваться как логическое значение; тест для '!= ноль'
вместо этого




Я не хочу проверять на ноль; я хочу проверить, если возвращенное значение true.



Я всегда должен делать if boolean == true если я работаю с дополнительным Bool?



Так как опционные не соответствуют BooleanType больше, разве компилятор не должен знать, что я хочу проверить значение Bool?

552   3  

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

    Ничего не найдено.