Table View Reload Sections Crashes

2020-07-08 03:45发布

问题:

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;
}

回答1:

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.



回答2:

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?



回答3:

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