问题
I'm using an NSMutableArray
referenced as 'stateArray'. stateArray needs to simply hold the BOOL
value for my cells to determine whether or not they are selected. here's my code..
stateArray in my .h:
@property (nonatomic, strong) NSMutableArray *stateArray;
Then stateArray is not synthesized. It needs to be filled with NO
throughout the array, so that when the cell becomes selected, NO can be replaced by YES. Currently this code is printing 0's for stateArray for every cell(the NSLog is in the if (showCheckmark == YES)
from my cellForRowAtIndexPath:
).
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
[[UITableViewCell appearance] setTintColor:[UIColor colorWithHexString:@"#669900"]];
#define CHECK_NULL_STRING(str) ([str isKindOfClass:[NSNull class]] || !str)?@"":str
static NSString *CellIdentifier = @"inviteCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
//Customization
cell.textLabel.highlightedTextColor = [UIColor colorWithHexString:@"#669900"];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.backgroundColor = [UIColor blackColor];
cell.textLabel.textColor = [UIColor whiteColor];
//Ignore this, it's for UISearchBar
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)];
_stateArray = [NSMutableArray array];
for (int i = 0 ; i != contactsObjects.count ; i++) [_stateArray addObject:@(NO)];
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 replaceObjectAtIndex:indexPath.row withObject:@(YES)];
[selectedObjects addObject:object];
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
[_stateArray replaceObjectAtIndex:indexPath.row withObject:@(NO)];
[selectedObjects removeObject:object];
}
//slow-motion selection animation.
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
回答1:
To keep track on selected items, use a Dictionary
instead of NSMutableArray
and keep the indexPath.row
as Key and selection as curresponding Value.
Also instead of doing these operations with array of BOOL's
, you can update the code as below.
@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;
}
}
Note: Don't forget remove the dictionary items from dictionary while reloading a new tableview dataset.
回答2:
BOOL
values are wrapped with NSNumber
, that's why you get 0's:
_stateArray = [NSMutableArray array];
for (int i = 0 ; i != contactsObjects.count ; i++) [_stateArray addObject:@(NO)];
BOOL showCheckmark = [[_stateArray objectAtIndex:indexPath.row] boolValue];
if (showCheckmark == YES)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
NSLog(@"It hit showCheckmark = YES, and stateArray is %@",[[_stateArray objectAtIndex:indexPath.row] boolValue] ? @"YES" : @"NO");
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
NSLog(@"It hit showCheckmark = NO, and stateArray is %@",[[_stateArray objectAtIndex:indexPath.row] boolValue] ? @"YES" : @"NO");
}
BOOL
is not object, so you cannot use the %@
format specifier. You need to handle this manually
回答3:
Try this,
Update your loop to populate _stateArray
by
for (int i = 0 ; i != contactsObjects.count ; i++) {
[_stateArray addObject:[NSNumber numberWithBool:NO]];
}
来源:https://stackoverflow.com/questions/21249219/using-bool-objects-in-nsmutablearray-to-determine-cell-statuses