การใช้ Swift ถ้าปล่อยให้มีตรรกะ AND ตัวดำเนินการ &&


93

เรารู้ว่าเราสามารถใช้if letคำสั่งเป็นชวเลขเพื่อตรวจสอบศูนย์ที่เป็นทางเลือกจากนั้นแกะออก

&&แต่ผมต้องการที่จะรวมที่มีการแสดงออกอื่นโดยใช้ตรรกะและผู้ประกอบการ

ตัวอย่างเช่นที่นี่ฉันทำโซ่เสริมเพื่อแกะและเลือกดาวน์แคสต์ 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คำสั่งไม่switchคำสั่งหรือ ternary ?ผู้ประกอบการ


เป็นความคิดที่ดีเสมอที่จะระบุข้อความแสดงข้อผิดพลาดในคำถาม
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 {
Max MacLeod

1
1. bridgeToObjectiveCหายไปในเบต้า 5 (และอาจไม่เคยมีไว้สำหรับการใช้งานทั่วไป) 2. มีfirstวิธีการในตัวของ Swift Arrayอยู่แล้ว
rickster

คำตอบ:


145

สำหรับ Swift 1.2 ตอนนี้ทำได้แล้ว สวิฟท์ 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 "where" จะถูกแทนที่ด้วยเครื่องหมายจุลภาค สิ่งที่เทียบเท่าจะเป็น:

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

2
นี่ควรเป็นคำตอบที่เลือกมา
Francis.Beauchamp

ใช่เพราะตอนนี้เปลี่ยนไปแล้ว คำตอบของไบรอันถูกต้องในเวลานั้น
Max MacLeod

59

ในตัวอย่างของSwift 3 Max MacLeod จะมีลักษณะดังนี้:

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

whereถูกแทนที่ด้วย,


10
ดังนั้นสำหรับ && มีไว้เพื่ออะไร || เหรอ?
jeet.chanchawat

9
@ jeet.chanchawat ตรรกะหรือไม่สมเหตุสมผลในบริบทนี้ if letจะดำเนินการต่อได้ก็ต่อเมื่อตัวเลือกนั้นคลายการปิดสำเร็จและถูกกำหนดให้กับชื่อตัวแปรใหม่ หากคุณพูดOR <something else>แล้วคุณสามารถข้ามจุดประสงค์ทั้งหมดของไฟล์if let. สำหรับตรรกะ OR ให้ทำแบบปกติifและภายในร่างกายจัดการกับข้อเท็จจริงที่ว่าวัตถุชิ้นแรกยังคงเป็นทางเลือก ณ จุดนั้น (ไม่ได้แกะออก)
jhabbott

37

คำตอบของ Max ถูกต้องและวิธีหนึ่งในการทำเช่นนี้ สังเกตว่าเมื่อเขียนด้วยวิธีนี้:

if let a = someOptional where someBool { }

someOptionalแสดงออกจะได้รับการแก้ไขเป็นครั้งแรก หากล้มเหลวsomeBoolนิพจน์จะไม่ได้รับการประเมิน (การประเมินการลัดวงจรตามที่คุณคาดหวัง)

หากคุณต้องการเขียนสิ่งนี้ในทางกลับกันสามารถทำได้ดังนี้:

if someBool, let a = someOptional { }

ในกรณีนี้someBoolจะได้รับการประเมินก่อนและเฉพาะในกรณีที่ประเมินว่าเป็นจริงเท่านั้นที่someOptionalนิพจน์จะถูกประเมิน


5

Swift 4ฉันจะใช้

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

4

มันเป็นไปไม่ได้.

จากไวยากรณ์ Swift

GRAMMAR ของงบ IF

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

if- เงื่อนไข→นิพจน์ | ประกาศ

else-clause → else code-block | อื่น ๆ if-statement

ค่าของเงื่อนไขใด ๆ ในคำสั่ง if ต้องมีชนิดที่สอดคล้องกับโปรโตคอล BooleanType เงื่อนไขนี้ยังสามารถเป็นการประกาศการผูกที่เป็นทางเลือกตามที่กล่าวไว้ในการผูกแบบเลือกได้

if-condition ต้องเป็นนิพจน์หรือการประกาศ คุณไม่สามารถมีทั้งการแสดงออกและการประกาศ

let foo = barเป็นการประกาศ แต่ไม่ได้ประเมินค่าที่เป็นไปBooleanTypeตาม fooมันประกาศคงที่ / ตัวแปร

โซลูชันดั้งเดิมของคุณดีพออ่านได้ง่ายกว่ามากจากนั้นรวมเงื่อนไขเข้าด้วยกัน


แต่แน่นอน "if let" - ซึ่งเป็นไวยากรณ์ Swift ที่ถูกต้อง - เป็นทั้งนิพจน์และการประกาศหรือไม่?
Max MacLeod

@MaxMacLeod let foo = barคือการประกาศไม่แสดงออก คุณทำไม่ได้let boolValue = (let foo = bar)
Bryan Chen

ตกลง แต่หากต้องการอ้างอิงคำแนะนำ Swift หน้า 11 ตัวอย่างคือ: if let name = optionalName optionalName ต้องเป็นนิพจน์โดยถ้า optionalName ไม่ใช่ทางเลือกจะประเมินเป็น true จากนั้นส่วนที่สองของคำสั่งจะเริ่มขึ้นโดยที่ตัวเลือกที่ไม่ได้ปิดจะถูกกำหนดให้กับชื่อ ดังนั้นคำถามคือถ้า "optionalName ไม่ใช่ตัวเลือก" เป็นนิพจน์สามารถขยายด้วยตรรกะ AND ได้หรือไม่ Btw ฉันคิดว่าคุณคงถูกต้องที่มันไม่สามารถทำได้
Max MacLeod

-1

ฉันคิดว่าโจทย์เดิมของคุณไม่เลวร้ายเกินไป ทางเลือก (messier) จะเป็น:

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

1
แต่คุณต้องเขียนโค้ดเพื่อแคสต์tabBarControllerอีกครั้ง
Bryan Chen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.