Быстрая хорошая практика кодирования: если инструкция с дополнительным типом Bool

Итак, я разрабатывал приложение в Swift, и сегодня я потратил почти час на отладку проблемы, которая оказалась совершенно неожиданной. Все это было результатом кода ниже.

if (hero.isAI) { //isAI is a Bool

}

Проблема заключалась в том, что этот оператор if ALWAYS возвратил true. Поэтому я подумал, что, возможно, я устанавливал isAI в true, но в конце я понял, что объявил isAI как необязательный тип, как показано ниже.

var isAI: Bool!

когда это должно было быть

var isAI: Bool

Это привело к тому, что if-statement не проверял, является ли isAI истинным, но вместо этого проверяет, содержит ли оно значение.

Итак, чтобы быть в безопасности, я обязательно буду писать мои if-statments, подобные этому

if (hero.isAI == true) { //isAI is a Bool

}

Итак, мой вопрос: , каковы мои варианты, чтобы избежать этой проблемы в будущем? (эта проблема кажется чрезвычайно опасной, особенно при работе над командой над крупным проектом). Должен ли я всегда писать свой if-statment явно, должен ли я просто избегать необязательного типа для Bools?

Обратите внимание, что у меня не было этой проблемы в Xcode Beta 2. Эта проблема возникла, когда я обновился до Xcode beta 3. Я думаю, потому что в Beta 2 Apple обрабатывает неявно развернутый Bool в if-statement, проверяя его значение, а не проверяя, содержит ли оно значение.

Наконец, ниже приведен пример того, какие if-statements запускаются с учетом необязательного Bool, чтобы лучше помочь людям понять проблему.

let myBool: Bool! = false

if (myBool) {
    //Runs
}

if (myBool!) {
    //Won't Run
}

if (!myBool) {
    //Runs
}

if (myBool == true) {
    //Won't Run
}

Ответ 1

Это известная проблема, которая отслеживается в репозитории SwiftInFlux, который включает эту цитату из Криса Латтнера на форумах разработчиков Apple.

Эта проблема существует с любым необязательным чем-то, что соответствует протокол LogicValue (например, вложенные опции, необязательные для bool, и т.д). Мы считаем это серьезной проблемой, которую нужно исправить на 1.0 и есть некоторые идеи, но еще не определились с решением.

Таким образом, эта проблема влияет не только на необязательные Bools, но и на любой необязательный тип, который соответствует протоколу LogicValue (определен как).

protocol LogicValue {
    func getLogicValue() -> Bool
}

В любом случае, что касается рекомендаций, как обойти это, трудно рекомендовать какое-либо одно конкретное решение, учитывая, что Apple не дала указание о том, как они намерены решить эту проблему в будущем, но я полагаю, что продолжать явно проверять значение Bool было бы хорошим способом.

if (hero.isAI == true) {
    // stuff    
}

Фактически, после некоторого дальнейшего прочтения цитата, приведенная выше, продолжает звучать так:

Для этого распространенного случая самый простой ответ - получить предупреждение за "если х" и требует, чтобы кто-то явно написал "если х! = ноль "или" если x == true ", чтобы сделать это явно, что они хотят.

Ответ 2

Мой совет - использовать этот хороший коалесцирующий ??

if textfieldDate.text?.isEmpty ?? true {
    // the text is either nil or empty but its all we want to know
}

Ответ 3

Если bool является частью Core Data (aka NSNumber), вы должны сделать это следующим образом.

if (isHero.isAI?.boolValue != nil)

Привет