【问题标题】:UITableViewCellAccessory Disappears When Scrolled Off Screen滚动离开屏幕时 UITableViewCell 附件消失
【发布时间】:2026-02-06 03:50:02
【问题描述】:

我有一个装满对象的 UITableView。在 didSelectRowAtIndexPath 方法中,我有一个 UITableViewCellAccessoryCheckmark 在选中行时出现,在未选中时消失。

didSelectRowAtIndexPath 方法的代码如下:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
 UITableViewCell *curCell = [beerTable cellForRowAtIndexPath:indexPath];

if (curCell.accessoryType == UITableViewCellAccessoryCheckmark) {
    [curCell setAccessoryType:UITableViewCellAccessoryNone];
    compareCount = (compareCount - 1);

    if (tableView == [[self searchDisplayController] searchResultsTableView]) {
        NSString *objBeer = [searchResults objectAtIndex:indexPath.row];
        [compareBeers removeObject:[searchResults objectAtIndex:indexPath.row]];
        [compareCarbs removeObject:[carbAmount objectAtIndex:[beerNames indexOfObject:objBeer]]];
    }
    else {
        [compareBeers removeObject:[beerNames objectAtIndex:indexPath.row]];
        [compareCarbs removeObject:[carbAmount objectAtIndex:indexPath.row]];
    }

}
else {
    [curCell setAccessoryType:UITableViewCellAccessoryCheckmark];
    compareCount = (compareCount + 1);

    if (tableView == [[self searchDisplayController] searchResultsTableView]) {
        NSString *objBeer = [searchResults objectAtIndex:indexPath.row];
        [compareBeers addObject:[searchResults objectAtIndex:indexPath.row]];
        [compareCarbs addObject:[carbAmount objectAtIndex:[beerNames indexOfObject:objBeer]]];
    }
    else {
        [compareBeers addObject:[beerNames objectAtIndex:indexPath.row]];
        [compareCarbs addObject:[carbAmount objectAtIndex:indexPath.row]];
    }

}

if (compareCount > 0) {
    if (compareOn == YES){
    }
    else {
    compareButton.enabled = YES;
    UIImage *image = [UIImage imageNamed:@"redbutton.png"];
    [compareButton setImage:image];
    }
}

else {
    compareButton.enabled = NO;
    [compareButton setImage:nil];
    [compareButton setCustomView:nil];
}

}

我也有这个作为我的cellForIndexPath

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {


static NSString *CellIdentifier = @"CustomCell";

CustomCell *cell = (CustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {

    NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];

    for (id currentObject in topLevelObjects){
        if ([currentObject isKindOfClass:[UITableViewCell class]]){
            cell =  (CustomCell *) currentObject;
            break;
        }
    }
}

// Setting separate tables correctly....


return cell;
}

My problem is that when the cell that is selected is scrolled out of view the checkmark associated with that value is now gone when back into view.

我应该怎么做才能使复选标记不消失?

谢谢

【问题讨论】:

    标签: iphone ios uitableview ios4


    【解决方案1】:

    当您滚动浏览数据时,您的单元格会被重新使用(这就是 dequeueReusableCellWithIdentifier 所做的)。在 didSelectRowAtIndexPath 中获得复选标记的单元格将被回收用于不同的行,并且不再与选中的行有任何连接。

    您需要在CellForrowatIndExpath中设置/解开附件视图,因此当签到的行滚动回到视图中时,它们会得到适当检查。

    【讨论】:

    • 如果我依靠用户点击来选择行,如何在 cellForRowAtIndexPath 中设置复选标记?你能给我举个例子吗?
    • 当他们点击行设置复选标记时,您需要将该信息存储在模型或控制器本身中。您可以做一些简单的事情,例如当用户单击一行时,通过索引路径将检查状态存储在字典中,然后使用它在 cellForRowAtIndexPath 中设置检查状态。
    【解决方案2】:

    对于任何想要更通用方法和多个选定单元格的人

    首先创建一个 (NSMutableArray *)selectedCells 来跟踪选定的单元格。 接下来实现2个委托方法

    -(void)tableView:(UITableView *)tableView 
        didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    
    //add the checkmark to cell when selected
    if ([tableView cellForRowAtIndexPath:indexPath].accessoryType == UITableViewCellAccessoryNone){
    [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
    
    }
    
    //once selected add that selected cell to the selectedCells array 
    
    [self.selectedCells addObject:@(indexPath.row) ];
    
    }
    

    -(void)tableView:(UITableView *)tableView 
                     didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{ 
    
    //set the accessory type back to none 
    if([tableView cellForRowAtIndexPath:indexPath].accessoryType == UITableViewCellAccessoryCheckmark){
    [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone;
    }
    
    //remove the selected cells index from the selectedCells array
    [self.selectedCells removeObject:@(indexPath.row) ];
    
    }
    

    现在,当您选择一个单元格时,会添加一个复选标记,并将 indexPath.row 存储到 NSMutableArray 中。当您取消选择该单元格时,它会删除复选标记并将其从数组中删除。这意味着该数组将仅保存已检查的单元格。

    然后我们使用该数组在 cellForRowAtIndexPath 方法中为单元格提供正确的附件类型。每次 tableView 需要一个单元格时调用此方法,我们告诉它是否在创建时需要有一个复选标记。

    -(UITableViewCell *)tableView:(UITableView *)tableView 
                    cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
     static NSString *CellIdentifier = @"Cell";
     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    
    if (cell == nil) {
      cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    
    //Create an NSNumber to hold the row of the cell to be created   
       NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:indexPath.row];
    
    //then ask the array if the selectedCells array has that object.
    //if it does then that cell needs a checkmark when created.
    
    if ([self.selectedCells containsObject:rowNsNum]){
       cell.accessoryType = UITableViewCellAccessoryCheckmark;
         }
    else { cell.accessoryType = UITableViewCellAccessoryNone;
         }
    
        [cell.textLabel setText:@"your contents"];
     }
    
     return cell;
     }
    

    【讨论】:

      【解决方案3】:

      UITableViewCell 在滚动时被回收。因此,当您再次上下滚动 tableView 时,您看到的单元格可能与之前可见的单元格不同。

      您需要每次在 cellForRowAtIndexPath 中重置单元格的状态。你的代码有这个评论区 // 正确设置单独的表......

      这是您进行设置的地方。当它被调用时,检查单元格是否应该显示一个复选标记,并相应地设置它

      【讨论】:

        【解决方案4】:

        尝试在 didSelectRow 方法中将选定单元格的选定索引存储在数组或字典中,并在 cellForRowAtIndexPath 中检查该索引是否在数组中可用,然后通过设置 accesoryType 选中该单元格。希望你能理解

        【讨论】:

          【解决方案5】:

          这是我认为效果最好的:

          (只是“添加这个”和“结束添加这个”之间的任何代码)

          另外,请确保将“(Your Number ofRows)”更改为返回 int 或本身为 int 的对象。比如myCustomArray.count,或者24。

          //In .h file add this
          NSMutableArray *indexArray;
          
          //in .m file 
          
          - (void)viewDidLoad {
              //Add this
              indexArray = [[NSMutableArray alloc] init];
              int i;
              for (i = 0; i <= (Your Number ofRows); i++) {
                  [indexArray addObject:[NSNumber numberWithDouble:0]];
              }
          NSLog(@"indexArray = %@",indexArray);//You can check the console now to see if you have an array of "zeros" 
              //End Add this
          }
          
          - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
          [tableView deselectRowAtIndexPath:indexPath animated:NO];
          UITableViewCell *curCell = [beerTable cellForRowAtIndexPath:indexPath];
          
          
          if (curCell.accessoryType == UITableViewCellAccessoryCheckmark) {
              [curCell setAccessoryType:UITableViewCellAccessoryNone];
              compareCount = (compareCount - 1);
          
              //Add this
              [indexArray replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithDouble:0]]; 
              //End Add this
          
          
              if (tableView == [[self searchDisplayController] searchResultsTableView]) {
                  NSString *objBeer = [searchResults objectAtIndex:indexPath.row];
                  [compareBeers removeObject:[searchResults objectAtIndex:indexPath.row]];
                  [compareCarbs removeObject:[carbAmount objectAtIndex:[beerNames indexOfObject:objBeer]]];
              }
              else {
                  [compareBeers removeObject:[beerNames objectAtIndex:indexPath.row]];
                  [compareCarbs removeObject:[carbAmount objectAtIndex:indexPath.row]];
              }
          
          }
          else {
              [curCell setAccessoryType:UITableViewCellAccessoryCheckmark];
              compareCount = (compareCount + 1);
          
              //Add this
              [indexArray replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithDouble:1]]; 
              //End Add this
          
              if (tableView == [[self searchDisplayController] searchResultsTableView]) {
                  NSString *objBeer = [searchResults objectAtIndex:indexPath.row];
                  [compareBeers addObject:[searchResults objectAtIndex:indexPath.row]];
                  [compareCarbs addObject:[carbAmount objectAtIndex:[beerNames indexOfObject:objBeer]]];
              }
              else {
                  [compareBeers addObject:[beerNames objectAtIndex:indexPath.row]];
                  [compareCarbs addObject:[carbAmount objectAtIndex:indexPath.row]];
              }
          
          }
          
          if (compareCount > 0) {
              if (compareOn == YES){
              }
              else {
                  compareButton.enabled = YES;
                  UIImage *image = [UIImage imageNamed:@"redbutton.png"];
                  [compareButton setImage:image];
              }
          }
          
          else {
              compareButton.enabled = NO;
              [compareButton setImage:nil];
              [compareButton setCustomView:nil];
          }
          
          }    
          
          
          
          - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
          
          
          static NSString *CellIdentifier = @"CustomCell";
          
          CustomCell *cell = (CustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
          if (cell == nil) {
          
              NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
          
              for (id currentObject in topLevelObjects){
                  if ([currentObject isKindOfClass:[UITableViewCell class]]){
                      cell =  (CustomCell *) currentObject;
                      break;
                  }
              }
          }
          
          // Setting separate tables correctly....
          
          //Add this
          if ([[indexArray objectAtIndex:indexPath.row] doubleValue] == 1) {
              cell.accesoryType = UITableViewCellAccesoryTypeCheckmark;
          } else {
              cell.accesoryType = UITableViewCellAccesoryTypeNone; 
          }
          //End Add this 
          
          return cell;
          }
          

          【讨论】: