简体   繁体   中英

Invalid update: invalid number of rows in section 0 when trying to expand and collapse UITableView sections

While debugging I found that in my numberOfRowInSection it is always returning the count and skipping over the the if !DealsDataService.instance.getKellysDeals()[section].isExpanded condition which is causing the error below since it wont return 0.

Would there be any reason why that condition would be getting skipped over?

Error: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (2) must be equal to the number of rows contained in that section before the update (2), plus or minus the number of rows inserted or deleted from that section (0 inserted, 2 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'

ViewController that is handling tableview and expanding and collapsing sections :

@IBOutlet weak var daysTable: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()


    daysTable.dataSource = self
    daysTable.delegate = self 
}

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{

    let view = UIView()
    view.backgroundColor = .black

    let headerLabel = UILabel()
    let button = UIButton(type: .system)

    let headerList = DaysService.instance.getHeader()
    headerLabel.textColor = .yellow
    headerLabel.font = UIFont.boldSystemFont(ofSize: 20)
    headerLabel.backgroundColor = .black
    headerLabel.text = headerList[section]

    button.setTitle("Close", for: .normal)
    button.setTitleColor(.yellow, for: .normal)
    button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
    button.addTarget(self, action: #selector(handleOpenClose), for: .touchUpInside)
    button.tag = section

    headerLabel.frame = CGRect(x: 5, y: 7.5, width: 150, height: 25)
    button.frame = CGRect(x: 150, y: 7.5, width: 150, height: 25)


    view.addSubview(headerLabel)
    view.addSubview(button)

    return view
}

@objc func handleOpenClose(button: UIButton)
{
    print("trying to expand....")
    let section = button.tag
    var dealsArray = DealsDataService.instance.getKellysDeals()

    var indexPaths = [IndexPath]()

    for deals in dealsArray[section].deals.indices
    {
        print(0, deals)

        let indexPath = IndexPath(row: deals, section: section)
        indexPaths.append(indexPath)
    }

    let isExpanded = dealsArray[section].isExpanded
    dealsArray[section].isExpanded = !isExpanded

    button.setTitle(isExpanded ? "Open" : "Close", for: .normal)

    //still having problem expanding and closing

    if isExpanded
    {
        dealsArray[section].deals.removeAll()
        daysTable.deleteRows(at: indexPaths, with: .fade)
    }
    else
    {
        self.daysTable.insertRows(at: indexPaths, with: .fade)
    }

}

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 40
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if !DealsDataService.instance.getKellysDeals()[section].isExpanded 
    {
        return 0
    }
    return DealsDataService.instance.getKellysDeals()[section].deals.count

}

func numberOfSections(in tableView: UITableView) -> Int {
    return DealsDataService.instance.getKellysDeals().count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "DaysCell", for: indexPath)
    let deals = DealsDataService.instance.getKellysDeals()[indexPath.section].deals[indexPath.row]
    cell.textLabel?.text = deals
    return cell

}

Data service that returns the array of deals:

static let instance = DealsDataService()
private(set) public var barNames = [Bars]()

public var kellysDeals = [

    ExpandableDeals(isExpanded: true, deals:["$2 Bud Lights", "$1 Tacos"]),//Monday
    ExpandableDeals(isExpanded: true, deals:["$2 Budweiser","$2 Burgers"]),//Tuesday
    ExpandableDeals(isExpanded: true, deals:["$3 Drafts","50 cent wings"]),//Wednesday
    ExpandableDeals(isExpanded: true, deals:["$8 Coors pitchers","$5 Sandwiches"]),//Thursday
    ExpandableDeals(isExpanded: true, deals:["No Deal"]),//Friday
    ExpandableDeals(isExpanded: true, deals:["No Deal"]),//Saturday
    ExpandableDeals(isExpanded: true, deals:["No Deal"])//Sunday
]

func getKellysDeals() -> [ExpandableDeals]
{
    return kellysDeals
}

}

In handleOpenClose I am calling the DataService when I should be declaring a global array variable then using that in my handleOpenClose function.

var barDeals: [ExpandableDeals] = []

@IBOutlet weak var daysTable: UITableView!

override func viewDidLoad()
{
    super.viewDidLoad()

    daysTable.dataSource = self
    daysTable.delegate = self

}

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{

    let view = UIView()
    view.backgroundColor = .black

    let headerLabel = UILabel()
    let button = UIButton(type: .system)

    let headerList = DaysService.instance.getHeader()
    headerLabel.textColor = .white
    headerLabel.font = UIFont.boldSystemFont(ofSize: 20)
    headerLabel.text = headerList[section]

    button.setTitle("Open", for: .normal)
    button.setTitleColor(.white, for: .normal)
    button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)
    button.addTarget(self, action: #selector(handleOpenClose), for: .touchUpInside)
    button.tag = section

    headerLabel.frame = CGRect(x: 5, y: 7.5, width: 150, height: 25)
    button.frame = CGRect(x: 150, y: 7.5, width: 150, height: 25)


    view.addSubview(headerLabel)
    view.addSubview(button)

    return view
}

@objc func handleOpenClose(button: UIButton)
{
    let section = button.tag

    self.daysTable.beginUpdates()
    var indexPaths = [IndexPath]()

    for deals in self.barDeals[section].deals.indices
    {
        let indexPath = IndexPath(row: deals, section: section)
        indexPaths.append(indexPath)
    }

    let isExpanded = self.barDeals[section].isExpanded
    self.barDeals[section].isExpanded = !isExpanded

    button.setTitle(!isExpanded ? "Close" : "Open", for: .normal)

    if isExpanded
    {
        daysTable.deleteRows(at: indexPaths, with: .fade)
    }
    else
    {
        daysTable.insertRows(at: indexPaths, with: .fade)
    }

    self.daysTable.endUpdates()

}

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 40
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    if self.barDeals[section].isExpanded == false
    {
        return 0
    }
    return self.barDeals[section].deals.count
}

func numberOfSections(in tableView: UITableView) -> Int {
    return self.barDeals.count
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM