การผูกตามเงื่อนไข: หากปล่อยให้เกิดข้อผิดพลาด - ตัวเริ่มต้นสำหรับการผูกตามเงื่อนไขต้องมีประเภทที่เป็นทางเลือก


120

ฉันกำลังพยายามลบแถวจากแหล่งข้อมูลและโค้ดบรรทัดต่อไปนี้:

if let tv = tableView {

ทำให้เกิดข้อผิดพลาดต่อไปนี้:

Initializer สำหรับการเชื่อมโยงตามเงื่อนไขต้องมีประเภทที่เป็นทางเลือกไม่ใช่ UITableView

นี่คือรหัสเต็ม:

// Override to support editing the table view.
func tableView(tableView: UITableView, commitEditingStyle editingStyle:UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == .Delete {

        // Delete the row from the data source

    if let tv = tableView {

            myData.removeAtIndex(indexPath.row)

            tv.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)

ฉันควรแก้ไขสิ่งต่อไปนี้อย่างไร?

 if let tv = tableView {

8
เนื่องจากtableViewไม่ใช่ค่าทางเลือกจึงไม่จำเป็นต้องตรวจสอบว่าเป็นศูนย์หรือไม่ ดังนั้นคุณสามารถใช้งานได้โดยตรงฉันหมายถึงลบสิ่งนั้นออกif let และใช้tableViewในฟังก์ชันเท่านั้น
Eric Qian

สำหรับคนรุ่นหลังหลังจากที่ฉันแก้ไขปัญหานี้แล้วฉันก็พบปัญหาvariable with getter/setter cannot have an initial valueซึ่งได้รับการแก้ไขโดยเพียงแค่ลบ {} บล็อกที่เหลือหลังจากการเริ่มต้นออกจากคำตอบนี้: stackoverflow.com/a/36002958/4544328
Jake T.

คำตอบ:


216

if let/ การif varรวมทางเลือกจะใช้งานได้ก็ต่อเมื่อผลลัพธ์ของด้านขวาของนิพจน์เป็นทางเลือก หากผลลัพธ์ของด้านขวาไม่ใช่ทางเลือกคุณจะไม่สามารถใช้การผูกที่เป็นทางเลือกนี้ได้ ประเด็นของการเชื่อมโยงที่เป็นทางเลือกนี้คือการตรวจสอบnilและใช้ตัวแปรหากไม่ใช่nilเท่านั้น

ในกรณีของคุณพารามิเตอร์ถูกประกาศเป็นชนิดที่ไม่เลือกtableView มันมีการประกันเพื่อไม่UITableView nilการผูกที่เป็นทางเลือกจึงไม่จำเป็น

func tableView(tableView: UITableView, commitEditingStyle editingStyle:UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == .Delete {
        // Delete the row from the data source
        myData.removeAtIndex(indexPath.row)
        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)

ทั้งหมดที่เราต้องทำคือการกำจัดif letและการเปลี่ยนแปลงที่เกิดขึ้นใด ๆอยู่ภายในเพียงtvtableView



16

ในกรณีที่คุณใช้ประเภทเซลล์ที่กำหนดเองพูด ArticleCell คุณอาจได้รับข้อผิดพลาดที่ระบุว่า:

    Initializer for conditional binding must have Optional type, not 'ArticleCell'

คุณจะได้รับข้อผิดพลาดนี้หากบรรทัดรหัสของคุณมีลักษณะดังนี้:

    if let cell = tableView.dequeReusableCell(withIdentifier: "ArticleCell",for indexPath: indexPath) as! ArticleCell 

คุณสามารถแก้ไขข้อผิดพลาดนี้ได้โดยทำดังต่อไปนี้:

    if let cell = tableView.dequeReusableCell(withIdentifier: "ArticleCell",for indexPath: indexPath) as ArticleCell?

หากคุณตรวจสอบข้างต้นคุณจะเห็นว่าส่วนหลังใช้การหล่อเสริมสำหรับเซลล์ประเภท ArticleCell


ในกรณีของฉันฉันจำเป็นต้องใช้as! ArticleCell?
lilbiscuit

9

เช่นเดียวกันกับคำสั่งยาม ข้อความแสดงข้อผิดพลาดเดียวกันนำฉันไปสู่โพสต์และคำตอบนี้ (ขอบคุณ @nhgrif)

รหัส: พิมพ์นามสกุลของบุคคลในกรณีที่ชื่อกลางมีความยาวน้อยกว่าสี่อักขระ

func greetByMiddleName(name: (first: String, middle: String?, last: String?)) {
    guard let Name = name.last where name.middle?.characters.count < 4 else {
        print("Hi there)")
        return
    }
    print("Hey \(Name)!")
}

จนกระทั่งฉันประกาศเป็นพารามิเตอร์ทางเลือกสุดท้ายฉันพบข้อผิดพลาดเดียวกัน


4

การผูกเงื่อนไขต้องมีประเภทที่เหมาะสมซึ่งหมายความว่าคุณสามารถผูกค่าทางเลือกในคำสั่ง if ให้เท่านั้น

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

    if editingStyle == .delete {

        // Delete the row from the data source

        if let tv = tableView as UITableView? {


        }
    }
}

วิธีนี้จะใช้งานได้ดี แต่ต้องแน่ใจว่าเมื่อคุณใช้ if let it must have optinal type "?"


0

มันจะยังสะดวกอยู่ (ในเชิงไวยากรณ์) ถ้าเราสามารถประกาศค่าปกติภายในเงื่อนไข if ได้ ดังนั้นนี่คือเคล็ดลับ: คุณสามารถทำให้คอมไพเลอร์คิดว่ามีการกำหนดOptional.some(T)ค่าให้เป็นดังนี้:

    if let i = "abc".firstIndex(of: "a"),
        let i_int = .some(i.utf16Offset(in: "abc")),
        i_int < 1 {
        // Code
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.