UITableView didSelectRowAtIndexPath在点击时添加额外的选中标记

5
在“didSelectRowAtIndexPath”中选择一个玩家并在所选行上添加勾号时,它会添加一个额外的勾号。
如果我点击第0行,它会将勾号添加到第0行和第11行。这意味着一个点击标记了两行。如果我点击第1行,它会向第10行添加一个额外的勾号,所以它会向前添加10行的勾号。似乎只是添加了勾号,而没有将该玩家添加到实际的玩家列表中。
非常感谢您的任何帮助。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

NSLog(@"indexPath: %i", indexPath.row);

// To many players selected
if (nrOfSelectedPlayers == 6) { //This is max players allowed
    UIAlertView *alertPlayer = [[UIAlertView alloc] initWithTitle:@"VARNING"
                                                          message:@"Du kan maximalt spela \n med sex spelare!" 
                                                         delegate:self 
                                                cancelButtonTitle:@"Tillbaka" 
                                                otherButtonTitles:nil];

    [alertPlayer show];
    [alertPlayer release];
    nrOfSelectedPlayers--;
    checkDeletePlayer = YES;
}
else { 

    // Handle the number of selected players to be able to delete player +6
    if (checkDeletePlayer == YES) {
        checkDeletePlayer = NO;
        nrOfSelectedPlayers++;
    }


    if (cell.accessoryType == UITableViewCellAccessoryNone) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
        [selectedPlayersArray addObject:cell.textLabel.text];
        nrOfSelectedPlayers++;
    } 
    else {
        cell.accessoryType = UITableViewCellAccessoryNone;
        selectedPlayer = cell.textLabel.text;

        for (int oo = 0; oo < nrOfSelectedPlayers; oo++) {
            if ([selectedPlayersArray objectAtIndex:oo] == cell.textLabel.text) {
                [selectedPlayersArray removeObjectAtIndex:oo];
                nrOfSelectedPlayers--;
            }
        }
        //nrOfSelectedPlayers--;
    }
}
}

1
谢谢你,伙计!你的问题和代码片段让我省去了再次提出重复问题的麻烦! - codejunkie
3个回答

7
我将使用故事板和动态原型单元格来显示一个州列表。在找到这个解决方案之前,我使用了上面的一些想法。
第一步:
@interface StateViewController : UITableViewController
{
    NSMutableArray *checkedIndexPaths;
}

第二步
(void)viewDidLoad
{
    [super viewDidLoad];
    self.states = [[GAIGStateStore sharedInstance]allStates];

    //Setup default array to keep track of the checkmarks
    checkedIndexPaths = [NSMutableArray arrayWithCapacity:self.states.count];
    for (int i = 0; i < self.states.count; i++) {
        [checkedIndexPaths addObject:[NSNumber numberWithBool:NO]];
    }
}

第三步
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    //This toggles the checkmark
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

    if (cell.accessoryType == UITableViewCellAccessoryNone)
    {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
        //This sets the array
        [checkedIndexPaths replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:YES]];

    } else
    {
        cell.accessoryType = UITableViewCellAccessoryNone;
         //This sets the array
        [checkedIndexPaths replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:NO]];

    }


}

第四步

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:stateCell forIndexPath:indexPath];

    UILabel *stateLabel = (UILabel *)[cell viewWithTag:1000];

    StateProvince *myState = [self.states objectAtIndex:indexPath.row];

    stateLabel.text = myState.label;

    //Now set the check marks
    // Assume cell not checked;
    [cell setAccessoryType:UITableViewCellAccessoryNone];

    NSNumber *num = [checkedIndexPaths objectAtIndex:indexPath.row];


    if (num == [NSNumber numberWithBool:YES]) {
           [cell setAccessoryType:UITableViewCellAccessoryCheckmark];
    }


    return cell;
}

代码模型很完美,但我有一个建议,你需要注释掉“dequeueReusableCellWithIdentifier”这一行,因为它会在滚动时使用相同的单元格来显示其他单元格,并在那里显示复选标记选项。 - Radix

6
您面临的问题是由于单元格重用引起的。
基本上,如果您的UITableView需要显示50个单元格,它只会创建10个并在您向下/向上滚动时重复使用它们。因此,您对第0行单元格所做的任何更改都将在第11行重新显示,因为TableView使用相同的单元格等。
您想要做的是独立于单元格跟踪已选择哪些玩家。您可以通过创建一个集合(例如NSMutableArray或NSMutableDictionary)轻松实现这一点,该集合将在NSNumber对象中存储BOOL值。
NSMutableArray *players = [NSMutableArray arrayWithCapacity:50];
for (int i = 0; i < 50; i++) {
    [players addObject:[NSNumber numberWithBool:NO]];
}

didSelectRowAtIndexPath:(NSIndexPath *)indexPath 方法中,您需要改变相应 NSNumber 对象的值,而不是对 cell 进行操作。
cellForRowAtIndexPath:(NSIndexPath *)indexPath 方法中,通过检查 players 集合中的相应条目来配置单元格附件。
或者,如果您真的非常固执,可以(这并不推荐)替换 cellForRowAtIndexPath:(NSIndexPath *)indexPath 中的以下行:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

使用:

UITableViewCell *cell = nil;

请问您能否在'cellForRowAtIndexPath'中展示一个例子? - PeterK

2

对于其他像我一样来到这里查看为什么他们的表格选择随机单元格的人,您需要在您的cellForRowAtIndexPath中添加类似以下内容的代码:

// Assume cell not checked;
[cell setAccessoryType:UITableViewCellAccessoryNone];
for (int i = 0; i < checkedIndexPaths.count; i++) {
    NSUInteger num = [[checkedIndexPaths objectAtIndex:i] row];

    if (num == indexPath.row) {
        [cell setAccessoryType:UITableViewCellAccessoryCheckmark];
    }
}

我有一个名为checkedIndexPaths的NSMutableArray,以便我知道哪些indexPath被选中。保留这样的数组可以轻松限制用户可以选择的单元格数量。以下是我的didSelectRowAtIndexPath的示例代码:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

    // uncheck if already checked
    if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
        cell.accessoryType = UITableViewCellAccessoryNone;
        [checkedIndexPaths removeObject:indexPath];
    }
    else {
        // make sure no more than 3 are selected
        if ([checkedIndexPaths count] < 3) {

            // check row
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
            // add it to our list of checked indexes
            [checkedIndexPaths addObject:indexPath];
        } else {
            UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Note" 
                                                            message:@"You can only select 3 rows." 
                                                           delegate:nil 
                                                  cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [alert show];
        }
    }  
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接