ส่วนที่ยุบได้: [ยืนยัน] ไม่สามารถกำหนดดัชนีแถวส่วนกลางใหม่สำหรับ preReloadFirstVisibleRow (0)


9

ฉันกำลังใช้ส่วนหัวของส่วนที่ยุบได้ใน UITableViewController

นี่คือวิธีที่ฉันกำหนดจำนวนแถวที่จะแสดงต่อส่วน:

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
    return self.sections[section].isCollapsed ? 0 : self.sections[section].items.count
}

มีโครงสร้างที่เก็บข้อมูลส่วนด้วยบูลสำหรับ 'isCollapsed'

นี่คือวิธีที่ฉันจะสลับสถานะของพวกเขา:

private func getSectionsNeedReload(_ section: Int) -> [Int]
{
    var sectionsToReload: [Int] = [section]

    let toggleSelectedSection = !sections[section].isCollapsed

    // Toggle collapse
    self.sections[section].isCollapsed = toggleSelectedSection

    if self.previouslyOpenSection != -1 && section != self.previouslyOpenSection
    {
        self.sections[self.previouslyOpenSection].isCollapsed = !self.sections[self.previouslyOpenSection].isCollapsed
        sectionsToReload.append(self.previouslyOpenSection)
        self.previouslyOpenSection = section
    }
    else if section == self.previouslyOpenSection
    {
        self.previouslyOpenSection = -1
    }
    else
    {
        self.previouslyOpenSection = section
    }

    return sectionsToReload
}



internal func toggleSection(_ header: CollapsibleTableViewHeader, section: Int)
{
    let sectionsNeedReload = getSectionsNeedReload(section)

    self.tableView.beginUpdates()
    self.tableView.reloadSections(IndexSet(sectionsNeedReload), with: .automatic)
    self.tableView.endUpdates()
}

ทุกอย่างทำงานและเคลื่อนไหวได้ดี แต่ในคอนโซลเมื่อยุบส่วนขยายฉันได้รับ [Assert]:

[ยืนยัน] ไม่สามารถกำหนดดัชนีแถวใหม่ส่วนกลางสำหรับ preReloadFirstVisibleRow (0)

สิ่งนี้เกิดขึ้นไม่ว่าจะเป็นส่วนที่เปิดเหมือนกันการปิด (ยุบ) หรือถ้าฉันเปิดส่วนอื่นและ 'ปิดอัตโนมัติ' ส่วนที่เปิดก่อนหน้านี้

ฉันไม่ได้ทำอะไรกับข้อมูล ที่ถาวร

ใครช่วยอธิบายสิ่งที่ขาดหายไปได้บ้าง ขอบคุณ


มุมมองตารางของคุณประกอบด้วยส่วนต่างๆมากมายและมีแถวจริง ๆ ไม่มาก
Byron Coetsee

คุณเคยจัดการเพื่อแก้ไขปัญหานี้หรือไม่?
PaulDoesDev

@ByronCoetsee ใช่จนกระทั่งมีการขยายส่วน ดังนั้นเมื่อทั้งหมดถูกยุบมันเป็นเพียงส่วนหัว เมื่อมีการขยายจะมีส่วนหัวทั้งหมดสำหรับส่วนที่ไม่ได้ขยายและส่วนหัวของส่วนจากนั้นเซลล์สำหรับข้อมูล
iOSProgrammingIsFun

@ PaulDoesDev ฉันได้ แต่ไม่ได้ใช้กลไกนี้ ฉันเขียนมันใหม่จนสมบูรณ์เพื่อที่ว่าในขณะที่มันจะดูเหมือนกัน อย่างไรก็ตามฉันจะออกจากที่นี่ในกรณีที่มีคนสามารถแก้ไขได้อย่างสง่างามหรือช่วยคนอื่นในทางใดทางหนึ่ง
iOSProgrammingIsFun

1
@iOSProgrammingIsFun ฮ่าฮ่าใช่ฉันคิดว่ามันอาจจะรู้สึกเหมือนแฮ็คและในทางเทคนิคแล้ว แต่ปริมาณของรหัสและความจริงที่ว่ามันสะอาดจริง ๆ แล้วหมายความว่าฉันสามารถปล่อยให้ตัวเองนอนในเวลากลางคืน: รหัส P โพสต์ด้านล่าง
Byron Coetsee

คำตอบ:


8

เพื่อให้ tableView รู้ว่ามันอยู่ที่ไหนในขณะที่มันกำลังโหลดแถว ฯลฯ มันพยายามค้นหา "anchor anchor" ซึ่งมันใช้เป็นข้อมูลอ้างอิง preReloadFirstVisibleRowนี้เรียกว่า เนื่องจาก tableView นี้อาจไม่มีแถวที่มองเห็นได้ในบางจุดเนื่องจากส่วนทั้งหมดที่ถูกยุบ tableView จะสับสนเนื่องจากไม่สามารถหาจุดยึดได้ จากนั้นจะรีเซ็ตเป็นด้านบน

วิธีแก้ไข: เพิ่มแถวความสูง 0 ลงในทุกกลุ่มที่ถูกยุบ ด้วยวิธีนี้แม้ว่าส่วนจะถูกยุบ แต่ก็ยังคงมีแถวอยู่ (แม้ว่าความสูง 0px) tableView จะมีบางสิ่งที่จะต้องเชื่อมโยงไปยังข้อมูลอ้างอิงเสมอ คุณจะเห็นสิ่งนี้มีผลบังคับใช้โดยการเพิ่มแถวในnumberOfRowsInSectionถ้า rowcount เป็น 0 และจัดการการindexPath.rowโทรใด ๆ เพิ่มเติมโดยตรวจสอบให้แน่ใจว่าได้ส่งคืนค่าเซลล์ phatom ก่อนindexPath.rowหากจำเป็นต้องdatasource.visibleRowsเป็น 0

สาธิตง่ายกว่าในรหัส:

func numberOfSections(in tableView: UITableView) -> Int {
    return datasource.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return datasource[section].visibleRows.count == 0 ? 1 : datasource[section].visibleRows.count
}

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    datasource[section].section = section
    return datasource[section]
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if datasource[indexPath.section].visibleRows.count == 0 { return 0 }
    return datasource[indexPath.section].visibleRows[indexPath.row].bounds.height
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if datasource[indexPath.section].visibleRows.count == 0 { return UITableViewCell() }

    // I've left this stuff here to show the real contents of a cell - note how
    // the phantom cell was returned before this point.

    let section = datasource[indexPath.section]
    let cell = TTSContentCell(withView: section.visibleRows[indexPath.row])
    cell.accessibilityLabel = "cell_\(indexPath.section)_\(indexPath.row)"
    cell.accessibilityIdentifier = "cell_\(indexPath.section)_\(indexPath.row)"
    cell.showsReorderControl = true
    return cell
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.