ExpandableCell 单元重用问题

ExpandableCell cell reuse issues

我正在尝试使用库 ExpandableCell 将可折叠 table 视图单元格添加到我的应用程序。我正在使用最新版本的库,即 1.3.0。

下面是完整代码。

import UIKit
import ExpandableCell

class ViewController: UIViewController {
    @IBOutlet weak var tableView: ExpandableTableView!

    private var passengers = [Passenger]()


    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.tableFooterView = UIView(frame: .zero)
        tableView.expandableDelegate = self

        passengers = [
            Passenger(id: 1, name: "Mark", trips: [Trip(id: 1, route: "NY to NJ")]),
            Passenger(id: 2, name: "Jesica", trips: [Trip(id: 1, route: "NY to NJ"), Trip(id: 2, route: "LA to LV")]),
            Passenger(id: 3, name: "Brian", trips: [Trip(id: 2, route: "Kansas City to Denver")])
        ]
        tableView.reloadData()
    }
}

extension ViewController: ExpandableDelegate {
    func expandableTableView(_ expandableTableView: ExpandableTableView, numberOfRowsInSection section: Int) -> Int {
        return passengers.count
    }

    func expandableTableView(_ expandableTableView: ExpandableTableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: PassengerCell.reuseIdentifier, for: indexPath) as! PassengerCell
        let passenger = passengers[indexPath.row]
        cell.textLabel?.text = passenger.name
        cell.detailTextLabel?.text = "\(passenger.trips?.count ?? 0) trips"
        return cell
    }

    func expandableTableView(_ expandableTableView: ExpandableTableView, expandedCellsForRowAt indexPath: IndexPath) -> [UITableViewCell]? {
        let cell = tableView.dequeueReusableCell(withIdentifier: TripCell.reuseIdentifier, for: indexPath) as! TripCell
        let passenger = passengers[indexPath.row]
        if let trips = passenger.trips {
            var cells = [TripCell]()
            for trip in trips {
                cell.textLabel?.text = trip.route
                cells.append(cell)
            }
            return cells
        } else {
            return nil
        }
    }

    func expandableTableView(_ expandableTableView: ExpandableTableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 60
    }

    func expandableTableView(_ expandableTableView: ExpandableTableView, heightsForExpandedRowAt indexPath: IndexPath) -> [CGFloat]? {
        let count = passengers[indexPath.row].trips?.count ?? 0
        let heightArray = [CGFloat](repeating: 50, count: count)
        return heightArray
    }

    func expandableTableView(_ expandableTableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
        return true
    }
}

数据加载正确,table视图按预期显示。但问题是当你点击折叠的单元格时。它的行为...很奇怪。

注意有些单元格根本没有出现(第二组应该显示 2 个黄色单元格)。并且有些单元格出现在它们不属于的其他组中。看起来是单元格重用问题。

我尝试覆盖 prepareForReuse 方法并手动重置控件,但这也不起作用。

override func prepareForReuse() {
    super.prepareForReuse()
    textLabel?.text = nil
    backgroundColor = nil
}

我在图书馆的 Github 回购中看到了一些类似的问题,但没有任何答案或修复。

如果有人以前使用过这个库,知道是什么导致了这个问题以及如何解决它吗?

Demo project

查看您的演示项目...

ViewController 中的 expandedCellsForRowAt 中,您正在创建 一个 单元格对象,然后为其分配不同的文本值并将其附加到数组。

func expandableTableView(_ expandableTableView: ExpandableTableView, expandedCellsForRowAt indexPath: IndexPath) -> [UITableViewCell]? {

    // here, you create a cell object
    let cell = tableView.dequeueReusableCell(withIdentifier: TripCell.reuseIdentifier, for: indexPath) as! TripCell

    let passenger = passengers[indexPath.row]
    if let trips = passenger.trips {
        var cells = [TripCell]()
        for trip in trips {
            // here, you repeatedly set the text of the SAME cell object
            cell.textLabel?.text = trip.route
            cells.append(cell)
        }
        return cells
    } else {
        return nil
    }
}

改用这个:

func expandableTableView(_ expandableTableView: ExpandableTableView, expandedCellsForRowAt indexPath: IndexPath) -> [UITableViewCell]? {

    // Don't create the cell here
    //let cell = tableView.dequeueReusableCell(withIdentifier: TripCell.reuseIdentifier, for: indexPath) as! TripCell

    let passenger = passengers[indexPath.row]
    if let trips = passenger.trips {
        var cells = [TripCell]()
        for trip in trips {
            // create a NEW cell for each trip (don't use indexPath)
            let cell = tableView.dequeueReusableCell(withIdentifier: TripCell.reuseIdentifier) as! TripCell
            cell.textLabel?.text = trip.route
            cells.append(cell)
        }
        return cells
    } else {
        return nil
    }
}