Dima Paliychuk
Dima Paliychuk

Reputation: 303

Insert section to UITableview

How to add a new section programmatically to UITableview?

I have pagination and when I try call insertSections in performBatchUpdates it works fine for the first time but when load second page UITableview does't update (no errors just not updated and do not called completion block).

private var periods = [PeriodHistoryModel]()

func fetchHistoryWith(models: [PeriodHistoryModel]) {
    guard models.count > 0 else {
        return
    }

    let newSectionsCount = models.count - periods.count
    let lastPeriod = periods.count - 1 >= 0 ? periods.count - 1 : 0

    var newRows: [IndexPath] = [IndexPath]()
    var newSections: [IndexSet] = [IndexSet]()

    let lastPeriodOldCount = periods.last?.sessions.count ?? 0
    let lastPeriodNewCount = models[lastPeriod].sessions.count
    let newSessionsCount = lastPeriodNewCount - lastPeriodOldCount

    if lastPeriod >= 0 {>
        for index in 0..<newSessionsCount {
            newRows.append(IndexPath(row: lastPeriodOldCount + index, section: lastPeriod))
        }
    }
    for index in 0..<newSectionsCount {
        let newSectionIndex = periods.count + index
        newSections.append(IndexSet(integer: newSectionIndex))
        for rowIndex in 0..<models[newSectionIndex].sessions.count {
            newRows.append(IndexPath(row: rowIndex, section: newSectionIndex))
        }
    }

    periods = models

    tableView.performBatchUpdates({
        for index in 0..<newSections.count {
            tableView.insertSections(newSections[index], with: .none)
        }
        tableView.insertRows(at: newRows, with: .none)
    })
}

reloadData does not fit need to do it smoothly

Upvotes: 3

Views: 8229

Answers (1)

Dinesh Selvaraj
Dinesh Selvaraj

Reputation: 644

The rule of thumb is "update table view models before performing batch updates". I just created a simple project and it works fine. So Make sure your delegate method numberOfSections return the updated model's count.

My project below.

class MyViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    var numberOfSections: Int = 1
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func insertSectionTapped(_ sender: Any) {
        numberOfSections += 1
        let indexSet = IndexSet(integer: numberOfSections - 1)
        tableView.performBatchUpdates({
            tableView.insertSections(indexSet, with: .none)
        }) { (update) in
            print("Update SUccess")
        }
    }
    
    @IBAction func insertRowTapped(_ sender: Any) {
    }
}

extension MyViewController: UITableViewDelegate, UITableViewDataSource {
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return numberOfSections
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 2
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell.init(style: .default, reuseIdentifier: "DefaultId")
        cell.textLabel?.text = "This is Section \(indexPath.section) - Row \(indexPath.row)"
        return cell
    }
}

Upvotes: 4

Related Questions