Anil Kothari
Anil Kothari

Reputation: 7733

UITableView reload section

I want to reload only one section not the full table. Is there any method in UITableView.

[tableView reloadData] is used to load full table.
I want to know how to load only one section, as I have large number of rows in the table.

Upvotes: 49

Views: 84880

Answers (11)

pableiros
pableiros

Reputation: 16032

For Swift 3, 4 and 5

let sectionToReload = 1
let indexSet: IndexSet = [sectionToReload]

self.tableView.reloadSections(indexSet, with: .automatic)

Upvotes: 21

ergunkocak
ergunkocak

Reputation: 3380

But you can reload only sections which contain same number of rows (or you have to manually add or remove them). Otherwise you will get an NSInternalInconsistencyException.

Steps:

  1. calculate which rows to remove and/or insert
  2. generate an IndexPath array from these
  3. call related tableView methods

now you can safely call reloadSections :) Reload section will call update for the rest of the indexes.

Or you can use a library like : https://github.com/onmyway133/DeepDiff

Swift pseodo code:


        tableView.deleteRows(at: valueIndexesToRemove, with: .automatic)
        tableView.insertRows(at: valueIndexesToInsert, with: .automatic)
        tableView.reloadSections(IndexSet([section]), with: .automatic)

Upvotes: 1

Vineesh TP
Vineesh TP

Reputation: 7963

Try to use

[self.tableView beginUpdates]; 
[self.tableView endUpdates];

Hope this will solve your issue.

Upvotes: 2

Ash
Ash

Reputation: 5712

Here is the method, you can pass section details in different ways

[self.tableView reloadSections:[[NSIndexSet alloc] initWithIndex:1] withRowAnimation:NO];

[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationNone];

Reloading particular sections improves performance for the table view as well some time it also avoid some issues like floating/moving custom headers-footers in your view. SO try to use reloadSection than relaodData whenever possible

Upvotes: 2

Ofir Malachi
Ofir Malachi

Reputation: 1286

that the correct way:

[self.tableView beginUpdates]; 
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];

Upvotes: 6

bandejapaisa
bandejapaisa

Reputation: 26952

The reloadSections method bugs me -- as I have to construct a few objects. This is great if you need the flexibility, but sometimes I also just want the simplicity too. It goes like this:

NSRange range = NSMakeRange(0, 1);
NSIndexSet *section = [NSIndexSet indexSetWithIndexesInRange:range];                                     
[self.tableView reloadSections:section withRowAnimation:UITableViewRowAnimationNone];

This will reload the first section. I prefer to have a category on UITableView and just call this method:

[self.tableView reloadSectionDU:0 withRowAnimation:UITableViewRowAnimationNone];

My category method looks like this:

@implementation UITableView (DUExtensions)

- (void) reloadSectionDU:(NSInteger)section withRowAnimation:(UITableViewRowAnimation)rowAnimation {
    NSRange range = NSMakeRange(section, 1);
    NSIndexSet *sectionToReload = [NSIndexSet indexSetWithIndexesInRange:range];                                     
    [self reloadSections:sectionToReload withRowAnimation:rowAnimation];
}

Upvotes: 71

Kamen Dobrev
Kamen Dobrev

Reputation: 1371

If you have custom section view you can add a weak reference to it in your view controller and update it whenever you want. Here is my code for reference:

@property (weak, nonatomic) UILabel *tableHeaderLabel;

....

-(UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UITableViewHeaderFooterView *myHeader = [[UITableViewHeaderFooterView alloc] init];

    UILabel *titleLabel = [[UILabel alloc] init];
    [titleLabel setFrame:CGRectMake(20, 0, 280, 20)];
    [titleLabel setTextAlignment:NSTextAlignmentRight];
    [titleLabel setBackgroundColor:[UIColor clearColor]];
    [titleLabel setFont:[UIFont systemFontOfSize:12]];

    [myHeader addSubview:titleLabel];

    self.tableHeaderLabel = titleLabel; //save reference so we can update the header later

    return myHeader;
}

Then later on you can update your section like this:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    self.tableHeaderLabel.text = [NSString stringWithFormat:@"Showing row: %ld", indexPath.row];
}

Upvotes: 0

Nick
Nick

Reputation: 2369

Based on the accepted answer here, I made a function that will reload all sections in the table using an animation. This could probably be optimized by reloading only visible sections.

[self.tableView reloadData];
NSRange range = NSMakeRange(0, [self numberOfSectionsInTableView:self.tableView]);
NSIndexSet *sections = [NSIndexSet indexSetWithIndexesInRange:range];
[self.tableView reloadSections:sections withRowAnimation:UITableViewRowAnimationFade];

In my case, I had to force a reloadData before the section animation, because the underlying data for the table had changed. It animates properly however.

Upvotes: 4

Inza
Inza

Reputation: 406

But you can reload only sections which contain same number of rows (or you have to manually add or remove them). Otherwise you will get:

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

Which is not required when you use [tableView reloadData].

When you need to reload a section and you have changed number of rows inside it, you could use something like this:

NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:section];

[self beginUpdates];
    [self deleteSections:indexSet withRowAnimation:rowAnimation];
    [self insertSections:indexSet withRowAnimation:rowAnimation];
[self endUpdates];

If you put it in a category (like bandejapaisa shows) it could look like this:

- (void)reloadSection:(NSInteger)section withRowAnimation:(UITableViewRowAnimation)rowAnimation {
    NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:section];

    [self beginUpdates];
        [self deleteSections:indexSet withRowAnimation:rowAnimation];
        [self insertSections:indexSet withRowAnimation:rowAnimation];
    [self endUpdates];
}

Upvotes: 27

Ankit Srivastava
Ankit Srivastava

Reputation: 12405

You need this... For Reload Row

- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation

or For Reload section

- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation

Upvotes: 2

sosborn
sosborn

Reputation: 14694

Yes, there is:

- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation

Upvotes: 37

Related Questions