Menggunakan Swift jika membiarkan dengan operator AND logis &&

93

Kita tahu bahwa kita dapat menggunakan if letpernyataan sebagai singkatan untuk memeriksa opsional nil kemudian membuka bungkusnya.

Namun, saya ingin menggabungkannya dengan ekspresi lain menggunakan operator AND logis &&.

Jadi, misalnya, di sini saya melakukan rangkaian opsional untuk membuka bungkus dan secara opsional men-downcast rootViewController saya ke tabBarController. Tapi daripada membuat pernyataan if bersarang, saya ingin menggabungkannya.

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

Pemberian gabungan:

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

Di atas memberikan kesalahan kompilasi Penggunaan pengenal yang belum terselesaikan 'tabBarController'

Menyederhanakan:

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

Ini memberikan kesalahan kompilasi Nilai terikat dalam pengikatan bersyarat harus berjenis Opsional . Setelah mencoba berbagai variasi sintaksis, masing-masing memberikan kesalahan compiler yang berbeda. Saya belum menemukan kombinasi pemenang dari urutan dan tanda kurung.

Jadi, pertanyaannya adalah, apakah mungkin dan jika demikian apa sintaks yang benar?

Perhatikan bahwa saya ingin melakukan hal ini dengan ifpernyataan tidak sebuah switchpernyataan atau ternary ?operator.

Max MacLeod
sumber
Itu selalu merupakan ide yang baik untuk memberikan pesan kesalahan dalam pertanyaan tersebut.
zaph
Pernyataan yang lebih sederhana untuk orang yang suka bereksperimen dengan ini:var foo : Int? = 10; if let bar = foo { if bar == 10 { println("Great success!") }}
DarkDust
Pesan kesalahan saat menggunakan if let bar = foo && bar == 10adalah Use of unresolved identifier "bar"(pada yang kedua bar, tentu saja).
DarkDust
hanya catatan bahwa saya bisa mempersingkat contoh di atas menggunakan firstObject Objective C sebagai berikut: if let navigationController = tabBarController.viewControllers.bridgeToObjectiveC (). firstObject as? UINavigationController {
Max MacLeod
1
1. bridgeToObjectiveChilang dalam beta 5 (dan sangat mungkin tidak pernah dimaksudkan untuk penggunaan umum). 2. Lagipula, ada firstmetode untuk Arraytipe bawaan Swift .
rickster

Jawaban:

143

Mulai Swift 1.2, ini sekarang dimungkinkan . The Swift 1.2 dan Xcode 6.3 beta catatan rilis negara:

Pembongkaran opsional yang lebih kuat dengan if let - Konstruksi if let sekarang dapat membuka beberapa opsional sekaligus, serta menyertakan kondisi boolean yang mengganggu. Ini memungkinkan Anda mengekspresikan aliran kontrol bersyarat tanpa penumpukan yang tidak perlu.

Dengan pernyataan di atas, sintaksnya menjadi:

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

Ini menggunakan whereklausa.

Contoh lain, kali ini mentransmisikan AnyObjectke Int, membuka bungkus opsional, dan memeriksa bahwa opsional yang tidak dibungkus memenuhi kondisi:

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

Untuk mereka yang sekarang menggunakan Swift 3, "di mana" telah diganti dengan koma. Oleh karena itu, padanannya adalah:

if let w = width as? Int, w < 500
{
    println("success!")
}
Max MacLeod
sumber
2
Ini harus menjadi jawaban yang dipilih.
Francis.Beauchamp
ya karena sekarang sudah berubah. Jawaban Bryan benar pada saat itu
Max MacLeod
59

Dalam Swift 3 Max MacLeod contoh akan terlihat seperti ini:

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

Itu wherediganti dengan,

ph1lb4
sumber
10
Jadi, untuk && untuk apa || ?
jeet.chanchawat
9
@ jeet.chanchawat logis ATAU tidak masuk akal dalam konteks ini. if lethanya dapat melanjutkan jika opsional berhasil dibuka dan ditetapkan ke nama variabel baru. Jika Anda mengatakannya OR <something else>maka Anda dapat dengan mudah melewati seluruh tujuan file if let. Untuk logika OR, lakukan saja normal ifdan di dalam tubuh berurusan dengan fakta bahwa objek pertama masih opsional pada saat itu (tidak terbuka).
jhabbott
37

Jawaban Max benar dan salah satu caranya. Perhatikan juga bahwa ketika ditulis seperti ini:

if let a = someOptional where someBool { }

The someOptionalekspresi akan diselesaikan terlebih dahulu. Jika gagal maka someBoolekspresi tidak akan dievaluasi (evaluasi hubung singkat, seperti yang Anda harapkan).

Jika Anda ingin menulis sebaliknya, dapat dilakukan seperti ini:

if someBool, let a = someOptional { }

Dalam hal someBoolini dievaluasi terlebih dahulu, dan hanya jika dievaluasi ke true, someOptionalekspresi dievaluasi.

par
sumber
5

Swift 4 , saya akan menggunakan,

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

Ini tidak mungkin.

Dari tata bahasa Swift

TATA BAHASA AN JIKA PERNYATAAN

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

if-condition → ekspresi | pernyataan

else-klausa → blok kode lain | lain jika-pernyataan

Nilai kondisi apa pun dalam pernyataan if harus memiliki tipe yang sesuai dengan protokol BooleanType. Kondisi tersebut juga dapat berupa deklarasi pengikatan opsional, seperti yang dibahas dalam Pengikatan Opsional

if-condition harus berupa ekspresi atau deklarasi. Anda tidak bisa memiliki ekspresi dan deklarasi.

let foo = baradalah deklarasi, tidak mengevaluasi ke nilai yang sesuai BooleanType. Ini mendeklarasikan konstanta / variabel foo.

Solusi asli Anda cukup baik, jauh lebih mudah dibaca daripada menggabungkan kondisi.

Bryan Chen
sumber
tetapi tentunya "if let" - yang merupakan sintaksis Swift yang valid - merupakan ekspresi dan deklarasi?
Max MacLeod
@AxLeod let foo = baradalah deklarasi bukan ekspresi. Anda tidak dapat melakukannyalet boolValue = (let foo = bar)
Bryan Chen
ok tapi untuk mengutip panduan Swift halaman 11, contohnya adalah: if let name = optionalName. optionalName harus berupa ekspresi di mana jika optionalName bukan opsional, ia dievaluasi menjadi true. Bagian kedua dari pernyataan itu kemudian dimulai di mana opsional yang tidak dibungkus ditetapkan ke nama. Jadi, pertanyaannya adalah, jika "optionalName bukan opsional" adalah sebuah ekspresi, dapatkah ia diperluas dengan logika AND. Btw Saya pikir Anda mungkin benar karena itu tidak bisa dilakukan.
Max MacLeod
-1

Saya pikir proposisi asli Anda tidak terlalu buruk. Alternatif (yang lebih berantakan) adalah:

if ((window!.rootViewController as? UITabBarController)?.viewControllers.count ?? 0) > 0 {
    println("do stuff")
}
jtbandes
sumber
1
tetapi Anda perlu membuat kode untuk cast tabBarControllerlagi
Bryan Chen