Використання Swift, якщо дозволено з логічним оператором І &&


93

Ми знаємо, що можемо використовувати if letоперацію як скорочення, щоб перевірити, чи не обов’язковий нуль, а потім розкрутити.

Однак я хочу поєднати це з іншим виразом, використовуючи логічний оператор AND &&.

Так, наприклад, тут я роблю необов’язковий ланцюжок для розгортання та необов’язково знижую свій rootViewController до tabBarController. Але замість того, щоб вкладати заяви, я хотів би їх поєднати.

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твердженням, а не з switchтвердженням або з трійковим ?оператором.


Завжди є гарною ідеєю надати повідомлення про помилки у питанні.
zaph

Більш просте твердження для людей, які люблять експериментувати з цим:var foo : Int? = 10; if let bar = foo { if bar == 10 { println("Great success!") }}
DarkDust

Повідомлення про помилку при використанні if let bar = foo && bar == 10є Use of unresolved identifier "bar"(на другому bar, звичайно).
DarkDust

лише примітка, що мені вдалося скоротити наведений вище приклад, використовуючи firstObject Objective C наступним чином: if let navigationController = tabBarController.viewControllers.bridgeToObjectiveC (). firstObject as? UINavigationController {
Макс Маклауд

1
1. bridgeToObjectiveCвийшов у бета-версію 5 (і, можливо, ніколи не був призначений для загального використання). 2. У будь-якому випадку існує firstметод для вбудованого Arrayтипу Swift .
рикстер

Відповіді:


143

Станом на Swift 1.2 це тепер можливо . У примітках до бета-версії Swift 1.2 та Xcode 6.3 зазначено :

Більш потужне необов’язкове розгортання за допомогою if let - конструкція if let тепер може розгортати декілька додаткових параметрів одночасно, а також включати в себе проміжні логічні умови. Це дозволяє виражати умовний потік управління без зайвого вкладання.

З наведеним вище твердженням синтаксис буде таким:

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, "де" замінено комою. Отже, еквівалентом буде:

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

2
Це має прийти обрана відповідь.
Френсіс Бошан

так, як зараз це змінилося. Відповідь Брайана на той час була правильною
Макс МакЛеод

58

У прикладі Swift 3 Max MacLeod буде виглядати так:

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

The whereбуло замінено на,


10
Отже, для && для чого || ?
jeet.chanchawat

9
@ jeet.chanchawat логічне АБО не має сенсу в цьому контексті. if letможе продовжуватись лише в тому випадку, якщо необов’язково успішно розгорнуто та призначено новій назві змінної. Якби ви сказали, OR <something else>тоді ви могли б легко обійти всю мету if let. Що стосується логічного АБО, просто зробіть нормальну ifі всередині тіла розібрайтеся з тим, що перший об'єкт все ще необов’язковий у цій точці (не розкручується).
jhabbott

37

Відповідь Макса правильна, і один із способів зробити це. Однак зверніть увагу, що, коли написано таким чином:

if let a = someOptional where someBool { }

someOptionalВираз буде вирішене першим. Якщо це не вдасться, someBoolвираз не буде оцінено (оцінка короткого замикання, як і слід було очікувати).

Якщо ви хочете написати це навпаки, це можна зробити так:

if someBool, let a = someOptional { }

У цьому випадку someBoolобчислюється спочатку, і лише якщо воно оцінюється як істина, someOptionalобчислюється вираз.


5

Свіфт 4 , я буду використовувати,

let i = navigationController?.viewControllers.index(of: self)
if let index = i, index > 0, let parent = navigationController?.viewControllers[index-1] {
    // access parent
}

4

Це неможливо.

З граматики Свіфт

ГРАМАТИКА ЗАЯВКИ ЩОБ

if-statement → if if-condition кодовий блок else-clauseopt

якщо-умова → вираз | декларація

речення else → кодовий блок else | else if-заява

Значення будь-якої умови в операторі if повинно мати тип, який відповідає протоколу BooleanType. Умовою також може бути необов'язкова декларація про обов'язковість, як обговорюється в додатковій прив'язці

if-умова має бути виразом або оголошенням. Ви не можете мати як вираз, так і декларацію.

let foo = barє декларацією, вона не оцінюється як значення, яке відповідає BooleanType. Він оголошує константу / змінну foo.

Ваше оригінальне рішення досить добре, воно набагато читабельніше, ніж поєднання умов.


але, безумовно, "якщо дозволити" - який є дійсним синтаксисом Swift - це одночасно вираз і оголошення?
Макс Маклеод

@MaxMacLeod let foo = bar- це декларація не вираз. ви не можете зробитиlet boolValue = (let foo = bar)
Брайан Чен

добре, але, щоб процитувати посібник Swift, сторінка 11, приклад: if let name = optionalName. optionalName має бути виразом, згідно з яким, якщо optionalName не є необов'язковим, воно має значення true. Друга частина заяви потім стартує, коли розгорнутому необов'язковому присвоюється ім'я. Отже, питання полягає в тому, що якщо «optionalName не є необов’язковим» - це вираз, чи можна його розширити логічним І. До речі, я думаю, ви, мабуть, праві, оскільки цього не можна зробити.
Макс Маклеод

-1

Я думаю, що ваша оригінальна пропозиція не надто погана. Альтернативою (месіє) може бути:

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

1
але вам потрібно буде кодувати tabBarControllerзнову, щоб брати участь знову
Брайан Чен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.