Table View Reload Sections Crashes
Asked Answered
M

3

9

I have a table view with 4 sections and 1-2 table view cells per section. The first cell has a uiswitch as an accessory view and controls the color theme of the app, switching between day mode and night mode. Once the switch is hit a function is called, changing the colors of the nav bar and background color. In that function I've also put the line

[self.tableview reloadData];

to update the table itself with the new colors. It works fine but theres no animation to it, so I used this instead

[self.tableView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 3)] withRowAnimation:UITableViewRowAnimationFade];

When that line is used the switch gets stuck and the app freezes. It doesn't crash per say, i.e. there is no crash log, it just freezes and the uiswitch stops mid animation.

I noticed that i can reload sections which don't have cells that contain accessory views and it works perfectly with the fade animation. I.e. this works

[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:2] withRowAnimation:UITableViewRowAnimationFade];

Because the third section does not have any cells with accessory views. But any section that has a cell that contains an accessory view (i.e. sections 0 and 2) if I try and reload it the app freezes.

Any ideas why this is happening? Below is my cellForRowAtIndexPath

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *cellIdentifier;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];

if (indexPath.section == 0) {

    cell.textLabel.text = [section0 objectAtIndex:indexPath.row];
    cell.accessoryType = UITableViewCellAccessoryNone;
    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    if (indexPath.row == 0) {

        cell.accessoryView = colorSchemeSwitch;
    }

    else if (indexPath.row == 1) {

        cell.accessoryView = autoLockSwitch;
    }
}

else if (indexPath.section == 1) {

    cell.textLabel.text = [section1 objectAtIndex:indexPath.row];
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}

else if (indexPath.section == 2) {

    cell.textLabel.text = [section2 objectAtIndex:indexPath.row];
    cell.accessoryType = UITableViewCellAccessoryNone;
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    cell.detailTextLabel.text = [NSString stringWithFormat:@"%i \t", (int)app.fontSize];
    fontSizeSlider.value = app.fontSize;
    cell.accessoryView = fontSizeSlider;
}

else if (indexPath.section == 3) {

    cell.textLabel.text = [section3 objectAtIndex:indexPath.row];
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    cell.detailTextLabel.text = app.color;
}

cell.backgroundColor = app.cellBackgroundColor;
cell.textLabel.textColor = app.textColor;
UIView *backgroundColorView = [[UIView alloc] init];
backgroundColorView.backgroundColor = app.cellSelectedColor;
[cell setSelectedBackgroundView:backgroundColorView];

return cell;
}
Melleta answered 5/11, 2014 at 13:12 Comment(3)
Please append Crash Log in your question.Deil
Its really bizarre, there is no crash log, the app freezes, it doesn't crash. The switch gets stuck in the middle and the app becomes unresponsive. No crash logMelleta
You can manage Objects of Table Cell. And Avoid much calculation in CellForRawAtIndexPath: Method. Keep that as simple as you can.Deil
G
9

I had the same issue in UITableViewCell comprising UISwitch. I solved the problem by calling [self.tableview reloadData] before reloading the sections:

NSIndexSet *sections = [[NSIndexSet alloc] initWithIndex:2];
[self.tableView reloadData];
[self.tableView reloadSections:sections withRowAnimation:UITableViewRowAnimationFade];

The same problem happens if you call:

[self.tableView reloadRowsAtIndexPaths:[self.tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationFade]

without reloading the data first.

Gilgilba answered 2/3, 2015 at 14:31 Comment(9)
Your are a legend! That worked perfectly. Can't believe it was this simpleMelleta
If we are calling reload table then why reloading section is needed for animation ? (H)Consubstantiation
I agree with @dip, either "reloadData" or "reloadSections" should be called, but not both. With that said, I randomly get a SIGABRT crash with using just "reloadSections" between "beingUpdates" and "endUpdates". I am still trying to figure out why...Aric
I agree with the above comments. Either use reloadData or reloadSections, both does not make senseLaconism
I believe you need to call reloadData at least once - in order for the numberOfSections delegate function to be called. Then you can call reloadSection as needed (and while your number of sections is not changing).Nourishing
why call reloadSections if you solve calling reload of entire table by reloadData ?Drinker
You should check out the solution here (add and removing the sections in an updates block) https://mcmap.net/q/349429/-uitableview-reload-sectionSidesaddle
Does this crash is iOS versions specific? , Seems like not getting the crash on iOS 10 and above but only getting on iOS 9.Kitts
If you have already called tableview.reload() no need to reload sections again.Belsky
Y
5

you haven't added a crash log but im guessing you are getting an error that states an existing number of rows in a section must be equal to some value before an update. If that's the case, Did you use [self.tableview beginUpdates] before reloading the table and [self.tableview endUpdates] after reloading?

Yost answered 5/11, 2014 at 15:3 Comment(6)
Thats the weird thing, there is no crash log, the app freezes, it doesn't crashMelleta
I've tried sandwiching the code with begin and end updates but no changeMelleta
try adding it here dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ //put code here});Yost
Tried that, code did not execute and the app still freezes. Again no crash log availableMelleta
Ok add it to the main thread by changing dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^ to just dispatch_get_main_queue(),Yost
Still the same result, app freezes, no crash logMelleta
L
0

I was getting the same issue, when trying to reload a specific row. there was a inconsistency in my dataSource. because i was loading data from remote. I found this link which solved the problem. But i needed to modify this line.

let sections = dataSource.numberOfSections?(in: self) ?? 0

To

let sections = dataSource.numberOfSections?(in: self) ?? 1

Locarno answered 12/2, 2020 at 10:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.