Использование Swift if let с логическим оператором AND &&

Мы знаем, что мы можем использовать оператор if let в качестве сокращения, чтобы проверить необязательный nil, а затем распаковать.

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

Итак, например, здесь я делаю необязательную цепочку для разворачивания и, возможно, опускаю свой rootViewController на tabBarController. Но вместо того, чтобы иметь вложенные операторы if, я хотел бы объединить их.

if let tabBarController = window!.rootViewController as? UITabBarController {
    if tabBarController.viewControllers.count > 0 {
        println("do stuff")
     }
 }

Комбинированное значение:

if let tabBarController = window!.rootViewController as? UITabBarController &&
    tabBarController.viewControllers.count > 0 {
        println("do stuff")
     }
}

Вышеприведенная ошибка компиляции Использование неразрешенного идентификатора 'tabBarController'

Упрощая:

if let tabBarController = window!.rootViewController as? UITabBarController && true {
   println("do stuff")
}

Это дает ошибку компиляции Связанное значение в условной привязке должно быть необязательного типа. Проведя различные синтаксические изменения, каждый из них дает другую ошибку компилятора. Мне еще предстоит найти выигрышную комбинацию порядка и круглых скобок.

Итак, вопрос в том, возможно ли и если да, то какой правильный синтаксис?

Обратите внимание, что я хочу сделать это с помощью инструкции if не a switch или тройного оператора ?.

Ответ 1

С Swift 1.2 этот теперь возможен. Swift 1.2 и Xcode 6.3 бета-версии выпуска:

Более мощная опция развертывания с, если let - The if let construct теперь можно развернуть сразу несколько опций, а также включить промежуточных булевых условий. Это позволяет выразить условные управляющий поток без ненужного вложения.

С приведенным выше утверждением синтаксис будет следующим:

if let tabBarController = window!.rootViewController as? UITabBarController where tabBarController.viewControllers.count > 0 {
        println("do stuff")
}

В этом случае используется предложение where.

Другой пример: на этот раз отбрасывание AnyObject в Int, развертывание необязательного и проверка того, что развернутый необязательный параметр соответствует условию:

if let w = width as? Int where w < 500
{
    println("success!")
}

Для тех, кто сейчас использует Swift 3, "where" заменено запятой. Таким образом, эквивалент:

if let w = width as? Int, w < 500
{
    println("success!")
}

Ответ 2

В Swift 3 Пример Max MacLeod будет выглядеть следующим образом:

if let tabBarController = window!.rootViewController as? UITabBarController, tabBarController.viewControllers.count > 0 {
    println("do stuff")
}

where был заменен на ,

Ответ 3

Максимальный ответ правильный и один из способов сделать это. Обратите внимание, что это написано следующим образом:

if let a = someOptional where someBool { }

Сначала выражение someOptional будет разрешено. Если это не удается, выражение someBool не будет оцениваться (оценка короткого замыкания, как и следовало ожидать).

Если вы хотите написать это, это может быть сделано так:

if someBool, let a = someOptional { }

В этом случае сначала оценивается someBool, и только если он вычисляет true, выполняется выражение someOptional.

Ответ 4

Это невозможно.

Из Swift grammar

ГРАММАТИЧЕСКОЕ ЗАЯВЛЕНИЕ

if-statement → if if-condition code-block else-clauseopt

if-condition → выражение | декларация

else-clause → else код-блок | else if-statement

Значение любого условия в операторе if должно иметь тип, соответствующий протоколу BooleanType. Условие также может быть необязательным объявлением связывания, как описано в разделе "Необязательное связывание"

if-condition должно быть выражением или декларацией. У вас не может быть выражения и декларации.

let foo = bar - это объявление, оно не оценивает значение, соответствующее BooleanType. Он объявляет константу/переменную foo.

Ваше оригинальное решение достаточно хорошее, оно более читаемо, а затем объединяет условия.

Ответ 5

Я думаю, что ваше оригинальное предложение не так уж плохо. Альтернативой (messier) будет:

if ((window!.rootViewController as? UITabBarController)?.viewControllers.count ?? 0) > 0 {
    println("do stuff")
}