保留UITableViewCellselect状态

我已经从字面上尝试了所有我能想到的事情。 任何人都可以找出为什么UITableViewCell不select,滚动,然后滚动后不重新加载复选标记?

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { #define CHECK_NULL_STRING(str) ([str isKindOfClass:[NSNull class]] || !str)?@"":str static NSString *CellIdentifier = @"inviteCell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; cell.accessoryType = UITableViewCellAccessoryCheckmark; cell.textLabel.highlightedTextColor = [UIColor colorWithHexString:@"#669900"]; cell.selectionStyle = UITableViewCellSelectionStyleGray; cell.backgroundColor = [UIColor blackColor]; cell.textLabel.textColor = [UIColor whiteColor]; [[UITableViewCell appearance] setTintColor:[UIColor colorWithHexString:@"#669900"]]; if (cell == nil) { cell = [[UITableViewCell alloc] init]; } if (cell == nil) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } BOOL isSearching = tableView != self.tableView; NSArray *arrayToUse = (isSearching ? searchResults : contactsObjects); id p = arrayToUse[indexPath.row]; NSString *fName = (__bridge_transfer NSString *)(ABRecordCopyValue((__bridge ABRecordRef)(p), kABPersonSortByFirstName)); NSString *lName = (__bridge_transfer NSString *)(ABRecordCopyValue((__bridge ABRecordRef)(p), kABPersonSortByLastName)); cell.textLabel.text = [NSString stringWithFormat:@"%@ %@", CHECK_NULL_STRING(fName), CHECK_NULL_STRING(lName)]; BOOL showCheckmark = [[stateArray objectAtIndex:indexPath.row] boolValue]; if (showCheckmark == YES) { cell.accessoryType = UITableViewCellAccessoryCheckmark; NSLog(@"It hit showCheckmark = YES, and stateArray is %@",stateArray[indexPath.row]); } else { cell.accessoryType = UITableViewCellAccessoryNone; NSLog(@"It hit showCheckmark = NO, and stateArray is %@",stateArray[indexPath.row]); } return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath; { id object = contactsObjects[indexPath.row]; UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; if (cell.accessoryType == UITableViewCellAccessoryNone) { cell.accessoryType = UITableViewCellAccessoryCheckmark; [stateArray insertObject:[NSNumber numberWithBool:YES] atIndex:indexPath.row]; [selectedObjects addObject:object]; } else { cell.accessoryType = UITableViewCellAccessoryNone; [stateArray insertObject:[NSNumber numberWithBool:NO] atIndex:indexPath.row]; [selectedObjects removeObject:object]; } //slow-motion selection animation. [tableView deselectRowAtIndexPath:indexPath animated:YES]; } 

你错过了! (逆运算符)在下面的行表示状态总是相同的。

 [stateArray replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:[[stateArray objectAtIndex:indexPath.row] boolValue]]]; 

它应该是

 [stateArray replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:![[stateArray objectAtIndex:indexPath.row] boolValue]]]; 

编辑—我重构了这两种方法,因为它可以用更less的代码来完成,它将完全简化你的方法。

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"inviteCell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; BOOL isSearching = tableView != self.tableView; NSArray *arrayToUse = (isSearching ? searchResults : contactsObjects); id p = arrayToUse[indexPath.row]; NSString *fName = (__bridge_transfer NSString *)(ABRecordCopyValue((__bridge ABRecordRef)(p), kABPersonSortByFirstName)); NSString *lName = (__bridge_transfer NSString *)(ABRecordCopyValue((__bridge ABRecordRef)(p), kABPersonSortByLastName)); cell.textLabel.text = [NSString stringWithFormat:@"%@ %@", CHECK_NULL_STRING(fName), CHECK_NULL_STRING(lName)]; BOOL showCheckmark = [stateArray[indexPath.row] boolValue]; if (showCheckmark == YES) { cell.accessoryType = UITableViewCellAccessoryCheckmark; } else { cell.accessoryType = UITableViewCellAccessoryNone; } return cell; } - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { id object = contactsObjects[indexPath.row]; UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; if (cell.accessoryType == UITableViewCellAccessoryNone) { cell.accessoryType = UITableViewCellAccessoryCheckmark; [selectedObjects addObject:object]; } else { cell.accessoryType = UITableViewCellAccessoryNone; [selectedObjects removeObject:object]; } stateArray[indexPath.row] = @(cell.accessoryType == UITableViewCellAccessoryCheckmark); } 

我build议更多的面向对象的方法。 这将确保您的代码是灵活的,并始终正确显示。

对于希望在表格中显示的每个项目,都有相应的对象。 你提到你正在显示联系人,所以我们假设你的对象被称为“联系人”:

 //Contact.h @interface Contact : NSObject @property BOOL selected; @property NSString *name; @end //Contact.m #import Contact.h @implementation Contact + (id) contactWithName:(NSString*)name { Contact *nContact = [Contact new]; nContact.name = name; nContact.selected = NO; return nContact; } @end 

然后,让你的观点像这样工作:

 //ContactView.m @interface ContactView() @property NSMutableArray *contacts; @end @implementation ContactView @synthesize contacts; - (void) viewDidLoad { [super viewDidLoad]; //get your contact list here. When creating contacts, be sure to assign their selected and their name as you require. contacts = @[[Contact contactWithName:@"John"], [Contact contactWithName:@"Jane"]]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellID = @"inviteCell"; UITableViewCell *cell = [tableview dequeueReusableCellWithIdentifier:cellID]; if (cell == nil) cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID]; Contact *cellContact = [contacts objectAtIndex:indexPath.row]; cell.textLabel.text = cellContact.name; cell.accessoryType = cellContact.selected == YES ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { Contact *cellContact = [contacts objectAtIndex:indexPath.row]; cellContact.selected = !cellContact.selected; [contacts replaceObjectAtIndex:indexPath.row withObject:cellContact]; [tableView reloadData]; //to refresh without animation //[tableView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [tableView numberOfSections])] withRowAnimation:UITableViewRowAnimationTop]; //to refresh with animation } @end 

繁荣,易于使用的表,总是看起来很正确,排队正确,并面向对象,以便日后维护方便。

即使insertObject被replace为replaceWithObject ,单元格select问题也没有解决,但是,不应该浪费时间在NSMutableArray设置NSInteger BOOL对象。 相反,对于单元格select内存,应该像这样使用NSDictionary

 @property (nonatomic, strong) NSMutableDictionary * selectedRowCollection; - (void)viewDidLoad{ self.selectedRowCollection = [[NSMutableDictionary alloc] init]; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath; { id object = contactsObjects[indexPath.row]; UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; if (cell.accessoryType == UITableViewCellAccessoryNone) { cell.accessoryType = UITableViewCellAccessoryCheckmark; [self.selectedRowCollection setObject:@"1" forKey:[NSString stringWithFormat:@"%d",indexPath.row]]; } else { cell.accessoryType = UITableViewCellAccessoryNone; [self.selectedRowCollection removeObjectForKey:[NSString stringWithFormat:@"%d",indexPath.row]]; } //slow-motion selection animation. [tableView deselectRowAtIndexPath:indexPath animated:YES]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { BOOL showCheckmark = [[self.selectedRowCollection valueForKey:[NSString stringWithFormat:@"%d",indexPath.row]] boolValue]; if (showCheckmark == YES) { cell.accessoryType = UITableViewCellAccessoryCheckmark; } else { cell.accessoryType = UITableViewCellAccessoryNone; } } 

如果这个答案帮助你,记得要把这个问题提出来! 谢谢!

你不是这样做的UITableViewCell *cell = [tableview dequeueReusableCellWithIdentifier:cellID]; if (cell == nil) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID]; } UITableViewCell *cell = [tableview dequeueReusableCellWithIdentifier:cellID]; if (cell == nil) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID]; } UITableViewCell *cell = [tableview dequeueReusableCellWithIdentifier:cellID]; if (cell == nil) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID]; }如果cell为零,分配是必要的。 或者在滚动时造成问题。