How to implement TableView.insertRows
Asked Answered
U

2

8

I am adding pagination to myTableview that presents blog posts. The data source is an array of posts, i.e. posts = [post].

I initially fetch 20 posts. I have a button that fetches the next 20 records. All of this is working fine. I can't figure how to insert these new records in the table without calling reloadData(). Can someone explain the following code? I don't understand what going on with the indexPaths on line 2 and 3 below. On:

IndexPath(row:(self.posts.count - 1)

Am I passing the last row of the original dataset or the updated one?

TableView.beginUpdates()
let indexPath:IndexPath = IndexPath(row:(self.posts.count - 1), section:0)
TableView.insertRows(at: [indexPath], with: .left)
TableView.endUpdates()
Unamuno answered 17/4, 2017 at 14:14 Comment(5)
If you add 20 rows, you have to pass it an array of 20 index paths, one for each new row.Septicidal
@Rob, I'm drawing a blank here. So if I add an additional 20 records to the first 20 then the first index path in the [indexPath] array would be row:20, section:0 ? Thanks!Unamuno
Yes, because row values in IndexPath are zero-based, the first new row (row 21) would be an IndexPath with a row of 20 and the last one would have a row of 39, for a total array of 20 new index paths.Septicidal
As an aside, you only need beginUpdates and endUpdates if you're doing multiple calls to update cells and you want them all to take place in one update. Since you're only doing one call to insertRows, no beginUpdates and endUpdates is needed. It doesn't hurt, but it's just not needed.Septicidal
Sorry Rob.. I thought I did! Thanks again.Unamuno
S
19

If you want to add items to your tableview, the value passed to insertRows will be an array of index paths for the new rows in your model object:

let additionalPosts = ...
posts += additionalPosts

let indexPaths = (posts.count - additionalPosts.count ..< posts.count)
    .map { IndexPath(row: $0, section: 0) }

tableView.insertRows(at: indexPaths, with: .left)

So, if you had 20 items in your array, and you add another 20 posts, the indexPaths would be:

[[0, 20], [0, 21], [0, 22], [0, 23], [0, 24], [0, 25], [0, 26], [0, 27], [0, 28], [0, 29], [0, 30], [0, 31], [0, 32], [0, 33], [0, 34], [0, 35], [0, 36], [0, 37], [0, 38], [0, 39]]


While I have attempted to answer the question, it should be noted that in 2019, Apple introduced a new pattern called “diffable data sources”. See WWDC 2019 video Advances in UI Data Sources and 2020’s Advances in diffable data sources. These completely eliminate the need to manually add items to a table view. One just updates the model, and then updates the “snapshot”, and the OS takes care of adding and removing of the individual cells for you. It will feel foreign the first time you use it, but once you go diffable, you will never go back. It makes life so much easier.

Note, these videos discuss both diffable data sources and composable layouts. While both greatly improve the table/collection view programming (and user) experience, you can tackle them separately. First, get your arms around the diffable data sources. You can tackle the composable layouts later.

Septicidal answered 17/4, 2017 at 14:39 Comment(0)
G
-1
    let intTempCount = messages.count ?? 0
    var indexPaths = [IndexPath]()

    messages.append(contentsOf: messageList)

    for index in intTempCount ..< (messages.count ?? 0) {
        let indexPathTobeAddedinTable = IndexPath(row: index, section: 0)
        indexPaths.append(indexPathTobeAddedinTable)
    }

    self.tableView.beginUpdates()
    self.tableView.insertRows(at: indexPaths, with: .bottom)
    self.tableView.endUpdates()
Granese answered 20/2 at 13:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.