问题
Edit:
The solution for this answer is related to iOS7 sometimes returning NSIndexPath
and other times returning NSMutableIndexPath
. The issue wasn't really related to begin/endUpdates
, but hopefully the solution will help some others.
All - I'm running my app on iOS 7, and I'm running into problems with the beginUpdates
and endUpdates
methods for a UITableView
.
I have a tableview that needs to change the height of a cell when touched. Below is my code:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// If our cell is selected, return double height
if([self cellIsSelected:indexPath]) {
return 117;
}
// Cell isn't selected so return single height
return 58;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
ChecklistItemCell *cell = (ChecklistItemCell *)[self.tableview cellForRowAtIndexPath:indexPath];
[cell.decreaseButton setHidden:NO];
[cell.increaseButton setHidden:NO];
// Toggle 'selected' state
BOOL isSelected = ![self cellIsSelected:indexPath];
DLog(@"%@", selectedIndexes);
DLog(@"is selected: %@", isSelected ? @"yes":@"no");
// Store cell 'selected' state keyed on indexPath
NSNumber *selectedIndex = @(isSelected);
selectedIndexes[indexPath] = selectedIndex;
[tableView beginUpdates];
[tableView endUpdates];
}
The beginUpdates
and endUpdates
methods are working pretty inconsistently. The didSelectRowAtIndexPath
method gets called correctly on each touch(I thought at first the UI was getting blocked), and the selectedIndexes
is storing alternating values correctly. The issue is, sometimes I touch a table cell and all the methods are called properly, but the cell height doesn't change. Anyone know what's going on?
回答1:
There is a change in behavior in iOS7 where index paths are sometimes instances of NSIndexPath
and other times UIMutableIndexPath
. The problem is that isEqual
between these two classes is always going to return NO
. Thus, you cannot reliably use index paths as dictionary keys or in other scenarios that rely on isEqual
.
I can think of a couple of viable solutions:
Write a method that always returns an instance of
NSIndexPath
and use it to generate keys:- (NSIndexPath *)keyForIndexPath:(NSIndexPath *)indexPath { if ([indexPath class] == [NSIndexPath class]) { return indexPath; } return [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section]; }
Identify rows by the data, not the index path. For example, if your data model is an array of
NSString
, use that string as the key into yourselectedIndexes
map. If your data model is an array ofNSManagedObjects
, use theobjectID
, etc.
I'm successfully using both of these solutions in my code.
EDIT Modified solution (1) based on @rob's suggestion of returning NSIndexPaths
rather than NSStrings
.
回答2:
endUpdates
shouldn't be called immediately after beginUpdates
. The latter's documentation states, "Begin a series of method calls that insert, delete, or select rows and sections of the receiver." That suggests that it should be called in willSelectRowAtIndexPath:
and endUpdates
should be called in didSelectRowAtIndexPath
.
来源:https://stackoverflow.com/questions/18919459/ios-7-beginupdates-endupdates-inconsistent