Mantıksal AND operatörü ile izin verildiğinde Swift kullanma &&


93

if letİsteğe bağlı bir sıfır olup olmadığını kontrol etmek için bir ifadeyi kısaltma olarak kullanabileceğimizi biliyoruz .

Ancak, bunu mantıksal AND işlecini kullanarak başka bir ifadeyle birleştirmek istiyorum &&.

Yani, örneğin, burada rootViewController'ımı tabBarController'a açmak ve isteğe bağlı olarak downcast etmek için isteğe bağlı zincirleme yapıyorum. Ancak if ifadeleri iç içe yerleştirmek yerine, onları birleştirmek istiyorum.

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

Kombine verme:

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

Yukarıdaki , çözümlenmemiş 'tabBarController' tanımlayıcısının kullanılması derleme hatası veriyor

Basitleştirme:

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

Bu, bir derleme hatası verir. Koşullu bağlamadaki Bağlı değer İsteğe Bağlı tipte olmalıdır . Çeşitli sözdizimsel varyasyonları denedikten sonra, her biri farklı bir derleyici hatası verir. Henüz emir ve parantezlerin kazanan kombinasyonunu bulamadım.

Öyleyse soru şu, mümkün mü ve eğer öyleyse doğru sözdizimi nedir?

Bir ile bunu yapmak istiyor unutmayın ifdeyimi değil bir switchdeyimi veya bir üçlü ?operatörü.


Sorudaki hata mesajlarını sağlamak her zaman iyi bir fikirdir.
zaph

Bunu var foo : Int? = 10; if let bar = foo { if bar == 10 { println("Great success!") }}
denemekten hoşlananlar

Kullanarak hata mesajı if let bar = foo && bar == 10olup Use of unresolved identifier "bar"(saniye bartabii).
DarkDust

sadece yukarıdaki örneği Objective C'nin firstObject'ini kullanarak aşağıdaki gibi kısaltabildiğimi not edin: let navigationController = tabBarController.viewControllers.bridgeToObjectiveC (). firstObject as? UINavigationController {
Max MacLeod

1
1. bridgeToObjectiveCbeta 5'e girdi (ve büyük olasılıkla hiçbir zaman genel kullanım için tasarlanmadı). 2. firstSwift'in yerleşik Arraytüründe zaten bir yöntem var .
rickster

Yanıtlar:


144

Swift 1.2'den itibaren bu artık mümkün . Swift 1.2 ve Xcode 6.3 beta sürüm notları durumu:

İf let ile daha güçlü isteğe bağlı sarmalama - if let yapısı artık birden çok seçeneği aynı anda açabilmenin yanı sıra araya giren boole koşullarını da içerebilir. Bu, gereksiz yuvalama yapmadan koşullu kontrol akışını ifade etmenize olanak tanır.

Yukarıdaki ifadeyle, sözdizimi şu şekilde olacaktır:

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

Bu, wheremaddeyi kullanır .

Başka bir örnek, bu kez döküm AnyObjectiçin Intisteğe bağlı ambalajını ve kullanıcıya bağlı şartı karşılamasıdır kontrol:

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

Swift 3'ü şimdi kullananlar için, "nerede" virgülle değiştirildi. Bu nedenle eşdeğeri şöyle olacaktır:

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

2
Bu seçilen cevap gelmelidir.
Francis.Beauchamp

evet şimdi değiştiği gibi. Bryan'ın cevabı o sırada doğruydu
Max MacLeod

59

In Swift 3 Max Macleod'ın örnek şu şekilde görünecektir:

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

whereİle değiştirildi,


10
Öyleyse, && için orada ne var || ?
jeet.chanchawat

9
@ jeet.chanchawat mantıksal VEYA bu bağlamda mantıklı değil. if letyalnızca isteğe bağlı başarıyla sarılmamışsa ve yeni değişken adına atanmışsa devam edebilir. Eğer söylediyseniz, OR <something else>o zaman kolayca tüm amacını atlayabilirsiniz if let. Mantıksal OR için, sadece normal yapın ifve gövdenin içinde ilk nesnenin o noktada hala isteğe bağlı olduğu (paketlenmemiş değil) gerçeğiyle ilgilenin.
jhabbott

37

Max'in cevabı doğru ve bunu yapmanın bir yolu. Ancak bu şekilde yazıldığında şuna dikkat edin:

if let a = someOptional where someBool { }

Önce someOptionalifade çözülecektir. Başarısız olursa, someBoolifade değerlendirilmeyecektir (beklediğiniz gibi kısa devre değerlendirmesi).

Bunu tam tersi şekilde yazmak istiyorsanız, şu şekilde yapılabilir:

if someBool, let a = someOptional { }

Bu durumda someBoolönce değerlendirilir ve yalnızca doğru olarak someOptionaldeğerlendirilirse ifade değerlendirilir.


5

Swift 4 , kullanacağım,

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

4

Mümkün değil.

Gönderen Swift dilbilgisi

EĞER İFADESİ DİLBİLGİSİ

if-ifadesi → if -koşul kod bloğu else-clauseopt

eğer-koşul → ifade | beyan

else cümlesi → else kod bloğu | else if-ifadesi

Bir if ifadesindeki herhangi bir koşulun değeri, BooleanType protokolüne uyan bir türe sahip olmalıdır. Koşul, İsteğe Bağlı Bağlamada tartışıldığı gibi isteğe bağlı bir bağlayıcı bildirim olabilir

if-koşulu ifade veya bildirim olmalıdır . Hem ifade hem de beyana sahip olamazsınız.

let foo = barbir beyandır, uygun bir değer olarak değerlendirilmez BooleanType. Bir sabit / değişken bildirir foo.

Orijinal çözümünüz yeterince iyi, koşulları birleştirmekten çok daha okunabilir.


ama kesinlikle "eğer izin ver" - geçerli Swift sözdizimi - hem bir ifade hem de bir bildiridir?
Max MacLeod

@MaxMacLeod let foo = barifade değil beyandır. yapamazsınlet boolValue = (let foo = bar)
Bryan Chen

tamam ama Swift rehberinden alıntı yapmak gerekirse, sayfa 11, örnek şudur: if let name = optionalName. OptionalName, isteğe bağlıAdı isteğe bağlı değilse true olarak değerlendirilen bir ifade olmalıdır. İfadenin ikinci bölümü daha sonra sarmalanmamış isteğe bağlı adın atandığı şekilde devreye girer. Öyleyse soru, "isteğe bağlıAdı isteğe bağlı değilse" bir ifadeyse, mantıksal VE ile genişletilebilir mi? Btw Bence yapılamayacağı için muhtemelen haklısınız.
Max MacLeod

-1

Bence orijinal öneriniz çok kötü değil. (Daha karmaşık) bir alternatif şudur:

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

1
ancak tabBarControlleryeniden kodlama yapmanız gerekiyor
Bryan Chen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.