为什么UITableViewCell
在选择,滚动,然后向后滚动后不重新加载复选标记?
- (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];
}
答案 0 :(得分:2)
您错过了以下行中的!
(逆运算符),这意味着状态将始终相同。
[stateArray replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:[[stateArray objectAtIndex:indexPath.row] boolValue]]];
应该是
[stateArray replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:![[stateArray objectAtIndex:indexPath.row] boolValue]]];
编辑---我重构了这两种方法,因为它可以用很少的代码完成,它将完全简化你的方法。
- (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);
}
答案 1 :(得分:1)
我建议采用更面向对象的方法。这将确保您的代码灵活并始终正确显示。
对于您希望在表格中显示的每个项目,都有一个相应的对象。您提到您正在显示联系人,因此我们假设您的对象名为“联系人”:
//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
繁荣,易于使用的表总是看起来正确,排队正确,并且面向对象以便以后轻松维护。
答案 2 :(得分:0)
即使将insertObject
替换为replaceWithObject
,单元格选择问题仍未解决,但是,不应该浪费时间设置BOOL
内有NSInteger
的对象NSMutableArray
。相反,对于细胞选择记忆,应该使用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;
}
}
答案 3 :(得分:-2)
你没有这样做UITableViewCell *cell = [tableview dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
如果单元格为零,则需要分配。或者在滚动时导致问题。