You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS 11 UITableView didSelect行选中异常求助:Cell标签值被错误替换

问题分析与解决方案

嘿,我看了你的代码,发现几个关键问题导致iOS11下选中行后Label显示默认文本:

1. 数组越界导致的文本赋值失败

在cellForRowAtIndexPath里,你给lblName赋值时用了indexPath.row-1:

cell.lblName.text = [[arrpickuprequest objectAtIndex:indexPath.row-1]valueForKey:@"Name"];

但你的表格第一行(indexPath.row == 0)是全选/全不选的控制行,这时候indexPath.row-1等于-1,直接访问数组的负索引会导致未定义行为。iOS10可能刚好没触发崩溃,但iOS11的数组越界检查更严格,导致这行的lblName没有被正确赋值,显示成Label的默认文本;当你选中行触发reloadData后,其他复用的cell也可能因为这个错误导致数据显示异常。

2. UITableViewCell复用逻辑缺失

你的代码里没有正确复用cell,没有调用dequeueReusableCellWithIdentifier:来获取复用cell,这在iOS11的UITableView复用机制调整后,会导致cell的状态混乱,数据显示错误。

修正后的代码示例

首先修正cellForRowAtIndexPath方法

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    // 先获取复用cell,记得提前给cell设置identifier(比如在xib/storyboard里设置)
    static NSString *cellIdentifier = @"PickupRequestCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (!cell) {
        // 如果没有复用cell,再创建(如果是xib的话用initWithNibName,storyboard的话一般不需要这步)
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
        // 这里假设你的cell是自定义的,需要初始化lblName和btncheck
        // 比如:cell.lblName = [[UILabel alloc] initWithFrame:CGRectMake(...)];
        // [cell.contentView addSubview:cell.lblName];
        // 同理初始化btncheck
    }

    // 处理第一行(全选行)
    if (indexPath.row == 0) {
        cell.lblName.text = @"全选"; // 设置全选行的文本,或者你需要的默认文本
    } else {
        // 其他行用indexPath.row-1访问arrpickuprequest
        cell.lblName.text = [[arrpickuprequest objectAtIndex:indexPath.row-1] valueForKey:@"Name"];
    }

    // 处理复选按钮
    cell.btncheck.tag = indexPath.row;
    if([[arrpickuprequestChecked objectAtIndex:indexPath.row] isEqualToString:@"Uncheck"]) {
        [cell.btncheck setImage:[UIImage imageNamed:@"uncheck"] forState:UIControlStateNormal];
    } else {
        [cell.btncheck setImage:[UIImage imageNamed:@"check"] forState:UIControlStateNormal];
    }
    // 注意:每次复用cell时,要先移除旧的target,避免重复添加
    [cell.btncheck removeTarget:self action:@selector(purchase_click:) forControlEvents:UIControlEventTouchUpInside];
    [cell.btncheck addTarget:self action:@selector(purchase_click:) forControlEvents:UIControlEventTouchUpInside];

    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    return cell;
}

其次检查didSelectRowAtIndexPath的数组操作

确保arrpickuprequestChecked的元素数量始终是arrpickuprequest.count + 1(因为包含第一行的全选状态),初始化的时候要正确设置:

// 初始化示例
arrpickuprequestChecked = [[NSMutableArray alloc] init];
// 先添加第一行的初始状态
[arrpickuprequestChecked addObject:@"Uncheck"];
// 再给每个请求添加初始状态
for (int i=0; i<arrpickuprequest.count; i++) {
    [arrpickuprequestChecked addObject:@"Uncheck"];
}

另外,在didSelectRowAtIndexPath里的循环可以优化一下,避免越界:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row == 0) {
        NSString *targetState = [[arrpickuprequestChecked objectAtIndex:0] isEqualToString:@"Uncheck"] ? @"Check" : @"Uncheck";
        // 遍历所有行(包括第一行)设置状态
        for (int i=0; i<arrpickuprequestChecked.count; i++) {
            [arrpickuprequestChecked replaceObjectAtIndex:i withObject:targetState];
        }
    } else {
        NSString *currentState = [arrpickuprequestChecked objectAtIndex:indexPath.row];
        NSString *newState = [currentState isEqualToString:@"Uncheck"] ? @"Check" : @"Uncheck";
        [arrpickuprequestChecked replaceObjectAtIndex:indexPath.row withObject:newState];
        
        // 如果取消选中某一行,要把全选行的状态改成Uncheck
        if ([newState isEqualToString:@"Uncheck"]) {
            [arrpickuprequestChecked replaceObjectAtIndex:0 withObject:@"Uncheck"];
        } else {
            // 可选:检查是否所有行都被选中,如果是,把全选行改成Check
            BOOL allChecked = YES;
            for (int i=1; i<arrpickuprequestChecked.count; i++) {
                if ([[arrpickuprequestChecked objectAtIndex:i] isEqualToString:@"Uncheck"]) {
                    allChecked = NO;
                    break;
                }
            }
            if (allChecked) {
                [arrpickuprequestChecked replaceObjectAtIndex:0 withObject:@"Check"];
            }
        }
    }
    [tblPickupreuest reloadData];
}

额外建议

  • 尽量用NSDictionary或者自定义模型来管理选中状态,而不是用字符串@"Check"/@"Uncheck",这样更安全易维护。
  • 开启Xcode的Address Sanitizer(Product > Scheme > Edit Scheme > Run > Diagnostics > Address Sanitizer),可以快速检测数组越界等内存问题。

内容的提问来源于stack exchange,提问作者Niharika

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:50:16