32

I'm trying to reload tableView section instead of reloading the whole tableview because I have a textfield in the header section and when I call self.tableView.reloadData() my keyboard get closed.

I've tried the code below but I get this error Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete row 5 from section 2 which only contains 4 rows before the update' So please where would be my issue?

    let newCount = self.placeArray.count

    var newIndexPaths = NSMutableArray(capacity: newCount)

    for var i = 0 ; i < newCount ; i++ {
    var indexPath = NSIndexPath(forRow: i, inSection: 2)
        newIndexPaths.addObject(indexPath)
    }

    self.tableView.beginUpdates()
    self.tableView.reloadRowsAtIndexPaths(newIndexPaths as [AnyObject], withRowAnimation: UITableViewRowAnimation.None)
    self.tableView.endUpdates()
CAN
  • 1,677
  • 4
  • 19
  • 28
  • 1
    Such code easily causes inconsistencies, don't be afraid to call the datasource method to get the number of rows. – A-Live Sep 07 '15 at 14:29
  • @A-Live I'm sorry I didn't understand how to make it? – CAN Sep 07 '15 at 14:33
  • Use `numberOfRowsInSection` instead of copying the logic from there, this way the number must always be correct. You haven't show or mention any modification of the number of rows so I assume you don't do that, otherwise you have to take care of changing the number accordingly depending on when you get the number and modify the datasource. – A-Live Sep 07 '15 at 14:52
  • I think you are giving me the solution but I'm not getting you. I'm updating the `numberOfRows` with the new array. @A-Live – CAN Sep 07 '15 at 15:14
  • You are trying to update more rows than there is, table view assumes you are trying to remove a row - that is caused by your mistake at calculation of the number of rows. – A-Live Sep 07 '15 at 15:42
  • Refer to [Reload section without reloading section header](https://stackoverflow.com/q/20802648/6521116) – LF00 May 17 '18 at 03:49

8 Answers8

45

You could use UITableView's reloadSections method instead.

tableView.reloadSections(IndexSet(integer: 2), with: .none)
Himanshu padia
  • 7,428
  • 1
  • 47
  • 45
hennes
  • 9,147
  • 4
  • 43
  • 63
  • How can I update the header and footer of a section: https://stackoverflow.com/questions/46531768/uitableview-grouped-section-footer-not-updating-after-reload – nr5 Oct 03 '17 at 02:41
  • For some reason I have to cast NSIndexSet to IndexSet in Swift 3: `self.myTableView.reloadSections(NSIndexSet(index: index) as IndexSet, with: .automatic)` – Liam Bolling Aug 26 '18 at 18:53
  • 13
    this will reload both the section and the section headerView. I'm surprised by the upvotes to this answer – iOS dev Sep 18 '18 at 22:53
  • 6
    This is not the correct answer, it is reloading the section header but it just has no animation – Joe Maher Oct 05 '18 at 03:12
  • 1
    This is not the right answer. This reloads the whole section including header – Faheem Rahman Dec 22 '21 at 06:09
23

Swift 3.0.1:

let sectionIndex = IndexSet(integer: 0)

tableView.reloadSections(sectionIndex, with: .none) // or fade, right, left, top, bottom, none, middle, automatic
Dani Pralea
  • 4,545
  • 2
  • 31
  • 49
15

Swift 3.1 Xcode 8.3.3 Answer :)

The problem is - each section includes header of course, so section is:

section = header + footer + rows

The answer is - reload rows directly by IndexPath. Example:

  1. Let's say you've got 1 section in your table and 'array' of something you use as datasource for table:

    let indexes = (0..<array.count).map { IndexPath(row: $0, section: 0) }

  2. Now we've got array of indexes of cell we want to reload, so:

    tableView.reloadRows(at: indexes, with: .fade)

11

Note:

  • UITableView.reloadData() will reload all the table. Docs about reloaddata

    reload all the data that is used to construct the table, including cells, section headers and footers, index arrays, and so on. For efficiency, the table view redisplays only those rows that are visible. It adjusts offsets if the table shrinks as a result of the reload. The table view’s delegate or data source calls this method when it wants the table view to completely reload its data.

  • UITableView.reloadSections(_ sections: IndexSet, with animation: UITableViewRowAnimation) will reload specific section( including section header and section footer). Docs about reloadsections

  • UITableView.reloadRows(at indexPaths: [IndexPath], with animation: UITableViewRowAnimation) will reload the specified rows. Docs about reloadRows

So here reloadSections will not works here. If your header section data and status not change, call this method will make no diffrence by sight.

Solution: use reloadRows to load the rows of all the sections or of the specific section. Note: here you can just load the visible rows, others will be loaded when you scroll you view. You also can refer to Get all indexPaths in a section for more solutions

var indexPaths = self.tableView.indexPathsForVisibleRows

/* just roload visible rows of specified section
indexPaths = indexPaths.filter({ (indexPath) -> Bool in
    return indexPath.section == SECTION_INDEX_NEED_TO_RELOAD
})
*/
self.tableView.reloadRows(at: indexPaths!, with: .none)
LF00
  • 27,015
  • 29
  • 156
  • 295
  • 2
    Hey, Good answer and good document. But when I call `reloadRows` my header will also reload, In my case my header is hidden. If you have any solution for this specific issue, please let me know. – Vivek Jul 03 '19 at 05:51
5

Swift 5

You can just reload section as below:

tableView.reloadSections([0], with: .none)

or

tableView.reloadSections(IndexSet(integer: 0), with: .none)

Here zero represent the index it will reload.

Reload multiple sections:

tableView.reloadSections([0, 1, 3], with: .none)
Parth Adroja
  • 13,198
  • 5
  • 37
  • 71
0

[Swift 5]

You want to reload all rows in a section. So you can do:

let rowIndexes: [IndexPath] = Array(0...YOUR_ARRAY-1).map({ 
    return IndexPath(row: $0, section: YOUR_SECTION) 
})

To get all possible row indexes for this section. Then you just have to reload rows for these indexes:

tableView.reloadRows(at: rowsIndexes, with: .fade)

The section won't be reloaded.

Paul Bénéteau
  • 775
  • 2
  • 12
  • 36
0

I might be late to the party but here is a solution for 2D array (in case if your tableView has sections and each section has some items). This will reload every cell in every section but won't touch header/footer of the section.

    let indexPaths = (0..<array.count).map { section in
        (0..<array[section].nestedArray.count).map { IndexPath(row: $0, section: section) }
    }.flatMap { $0 }
    tableView.reloadRows(at: indexPaths, with: .fade)
Sapozhnik Ivan
  • 235
  • 3
  • 7
-1

Swift 5

Here is put static index reload which is 1st index, you can change as per your requirement.

self.tblView.reloadSections(IndexSet(index: 1), with: .none)
Vivek
  • 4,916
  • 35
  • 40