【问题标题】:TableView cell reuse causing the button title to change while scrollingTableView 单元格重用导致按钮标题在滚动时更改
【发布时间】:2015-06-22 05:39:39
【问题描述】:

我有一个显示名称和标题为“关注”按钮的列表。当我点击按钮标题应更改为“取消关注”。如果我再次点击按钮,标题应再次更改为“关注”。这工作正常,但是当我滚动表格时,其他单元格的标题也会由于单元格重用而发生变化。

代码如下:

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

    static NSString *CellIdentifier = @"AuthorsListCell";
    AuthorsListTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier
                                                                     forIndexPath:indexPath];
    dic_eachAuthor = [[_arr_authors objectAtIndex:indexPath.row] mutableCopy];

    cell.lbl_authorName.text = [dic_eachAuthor objectForKey:@"name"];
    cell.btn_followOrUnfollow.tag = indexPath.row;

    if([dic_eachAuthor valueForKey:@"follow"]){
        [cell.btn_followOrUnfollow setTitle:@"UnFollow" forState:UIControlStateNormal];
    }
    else{

        [cell.btn_followOrUnfollow setTitle:@"Follow" forState:UIControlStateNormal];
    }

    // action button method declarations
    [cell.btn_followOrUnfollow addTarget:self action:@selector(followOrUnfollow:) forControlEvents:UIControlEventTouchUpInside];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    return cell;
}


    -(void)followOrUnfollow:(UIButton *)sender
{
    if ([sender.titleLabel.text isEqualToString:@"Follow"]) {
        [sender setTitle:@"UnFollow" forState:UIControlStateNormal];
        [dic_eachAuthor setValue:@"1" forKey:@"follow"];

    }
    else if ([sender.titleLabel.text isEqualToString:@"UnFollow"]) {
        [sender setTitle:@"Follow" forState:UIControlStateNormal];
        [dic_eachAuthor setValue:nil forKey:@"follow"];


    }


}

请提出一些防止单元重复使用的建议。

【问题讨论】:

  • 为“如果单元格为 nil”添加代码,因为每次初始化新单元格时。所以你正面临这个问题。 cell = (ListTableViewCell *)[[ListTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: CellIdentifier];
  • 不,它不能解决问题。

标签: ios uitableview uibutton reuseidentifier


【解决方案1】:

在 cellForRowAtIndexPath 的 followOrUnfollow 中也添加此条件

if ([sender.titleLabel.text isEqualToString:@"Follow"]) {
        [sender setTitle:@"UnFollow" forState:UIControlStateNormal];

    }
    else if ([sender.titleLabel.text isEqualToString:@"UnFollow"]) {
        [sender setTitle:@"Follow" forState:UIControlStateNormal];


    }

【讨论】:

    【解决方案2】:

    在数据源中存储关注/取消关注状态信息。

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
        static NSString *CellIdentifier = @"CellIdentifier";
        ListTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier
                                                                         forIndexPath:indexPath];
    
        cell.lbl_authorName.text = [[_arr_authors objectAtIndex:indexPath.row] objectForKey:@"name"];
        cell.btn_followOrUnfollow.tag = indexPath.row;
    
        // action button method declarations
        [cell.btn_followOrUnfollow addTarget:self action:@selector(followOrUnfollow:) forControlEvents:UIControlEventTouchUpInside];
    
        NSString *btnTitle = [[_arr_authors objectAtIndex:indexPath.row] objectForKey:@"userFollowUnfollow"];
         [sender setTitle:btnTitle forState:UIControlStateNormal];
    
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
    
        return cell;
    }
    
    -(void)followOrUnfollow:(UIButton *)sender
    {
        if ([sender.titleLabel.text isEqualToString:@"Follow"]) {
            [sender setTitle:@"UnFollow" forState:UIControlStateNormal];
    
        }
        else if ([sender.titleLabel.text isEqualToString:@"UnFollow"]) {
            [sender setTitle:@"Follow" forState:UIControlStateNormal];
        }
    
        [[_arr_authors objectAtIndex:sender.tag]  setValue:sender.titleLabel.text forKey:@"userFollowUnfollow"];
    
    }
    

    【讨论】:

    • 添加这些行会导致按钮标题显示为空白,当我点击按钮时应用程序崩溃。
    【解决方案3】:

    当您最初填充表格行时,您从此处的数组cell.lbl_authorName.text = [[_arr_authors objectAtIndex:indexPath.row] objectForKey:@"name"]; 执行此操作。问题是您没有从该数组中填充关注或取消关注信息。所以你所做的只是切换一个按钮,并且没有保存该按钮的状态。您需要做的是修改数组以有一个地方来保存关注/取消关注状态。然后从此数组中填充表格单元格中的状态。那么当你调用followOrUnfollow:时你需要修改数组中的状态。

    当单元格被重用时,它会检查原始数组以填充它,从数组中填充后续元素,然后您将被设置。

    编辑添加了一些代码:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
        static NSString *CellIdentifier = @"CellIdentifier";
        ListTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier                                                                     forIndexPath:indexPath];
    
        cell.lbl_authorName.text = [[_arr_authors objectAtIndex:indexPath.row] objectForKey:@"name"];
        cell.btn_followOrUnfollow.tag = indexPath.row;
        if([[_arr_authors objectAtIndex:indexPath.row] valueForKey:@"follow"]){
              [cell.btn_followOrUnfollow setTitle:@"UnFollow" forState:UIControlStateNormal];
        else{
             [cell.btn_followOrUnfollow setTitle:@"Follow" forState:UIControlStateNormal];
        }
    
        // action button method declarations
        [cell.btn_followOrUnfollow addTarget:self action:@selector(followOrUnfollow:) forControlEvents:UIControlEventTouchUpInside];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
    
        return cell;
    }
    
    -(void)followOrUnfollow:(UIButton *)sender
    {
        if ([sender.titleLabel.text isEqualToString:@"Follow"]) {
            [sender setTitle:@"UnFollow" forState:UIControlStateNormal];
            [[_arr_authors objectAtIndex:sender.tag] setValue:1 forKey:@"follow"]
        }
        else if ([sender.titleLabel.text isEqualToString:@"UnFollow"]) {
            [sender setTitle:@"Follow" forState:UIControlStateNormal];
            [[_arr_authors objectAtIndex:sender.tag] setValue:0 forKey:@"follow"]
        }
    }
    

    我不在我的普通机器上,所以语法可能不正确,但你应该明白了。另请注意,您必须将 follow 属性添加到 _arr_authors

    【讨论】:

    • 你能告诉我如何用一些代码来做。感谢您的建议。
    • 例如添加了代码示例,语法可能不正确但概念在那里,祝你好运!
    • 字典中follow key的初始值应该是多少?
    • 无论您的默认值是什么,我的猜测是您的默认值没有遵循,所以它会是 0。
    • 请查看问题中已编辑的代码,它仍然无法正常工作。每当我滚动回顶部时,即使在它们被点击之后,标题也会再次变为“关注”。然而,底部单元格现在没有更改数据。跟随键的默认值也是 nil
    【解决方案4】:

    你在这里遗漏了一些东西,试试这个:

    -(void)followOrUnfollow:(UIButton *)sender
    {
        NSDictionary *dict = (NSDictionary *) _arr_authors[sender tag];
        if ([[dict objectForKey:@"name"] isEqualToString:@"Follow"]) 
         {
            [sender setTitle:@"UnFollow" forState:UIControlStateNormal];
    
         }
         else if ([[dict objectForKey:@"name"] isEqualToString:@"UnFollow"]) 
        {
            [sender setTitle:@"Follow" forState:UIControlStateNormal];
        }
    }
    

    【讨论】:

      【解决方案5】:

      你是重复使用的单元格,所以请在 AuthorsListTableViewCell 中实现这个方法:

      -(void) prepareForReuse{
        [super prepareForReuse];
        [self.btn_followOrUnfollow setTitle:@"Follow" forState:UIControlStateNormal];
      }
      

      // 如果单元格是可重用的(具有重用标识符),则在从表格视图方法 dequeueReusableCellWithIdentifier: 返回单元格之前调用它。如果你覆盖,你必须调用 super。 并为单元格设置正确的默认值。

      我也推荐这样实现:

        - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
      
          static NSString *CellIdentifier = @"AuthorsListCell";
          AuthorsListTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier
                                                                           forIndexPath:indexPath];
      
          cell.lbl_authorName.text = [dic_eachAuthor objectForKey:@"name"];
          cell.btn_followOrUnfollow.tag = indexPath.row;
      
          [cell.btn_followOrUnfollow setTitle:@"Follow forState:UIControlStateNormal];
          [cell.btn_followOrUnfollow setTitle:@"UnFollow" forState:UIControlStateSelected];
      
          if([dic_eachAuthor valueForKey:@"follow"]){
              cell.btn_followOrUnfollow.selected = YES;
          } else{
              cell.btn_followorUnfollow.selected = NO;
          }
          // action button method declarations
          [cell.btn_followOrUnfollow addTarget:self action:@selector(followOrUnfollow:) forControlEvents:UIControlEventTouchUpInside];
          cell.selectionStyle = UITableViewCellSelectionStyleNone;
      
          return cell;
      }
      
      
          -(void)followOrUnfollow:(UIButton *)sender
      {
          sender.selected = !sender.selected;
      
          if ([sender.titleLabel.text isEqualToString:@"Follow"]) {
              [dic_eachAuthor setValue:@"1" forKey:@"follow"];
          }
          else if ([sender.titleLabel.text isEqualToString:@"UnFollow"]) {
              [dic_eachAuthor setValue:nil forKey:@"follow"];
          }
      
      
      }
      

      在 AuthorsListTableViewCell 中

      -(void) prepareForReuse{
        [super prepareForReuse];
        self.btn_followOrUnfollow.selected = NO;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多