在 tableView 中修改 UITableViewCell 附件类型时出现问题:didSelectRowAtIndexPath:

Posted

技术标签:

【中文标题】在 tableView 中修改 UITableViewCell 附件类型时出现问题:didSelectRowAtIndexPath:【英文标题】:Problem modifying UITableViewCell accessoryType in tableView:didSelectRowAtIndexPath: 【发布时间】:2010-10-26 09:48:44 【问题描述】:

我有一个透明的表格视图(带有子视图 UIImageView 的 UIViewController,以及位于 UIImageView 兄弟之上的另一个子视图 UITableView,背景 = clearColor,UITableViewCells 背景 = clearColor)。我还希望点击单元格以在复选标记和无之间切换单元格的附件类型。如果我在 tableView:didSelectRowAtIndexPath: 中修改 UITableViewCell 的附件类型,有时(30-50% 的时间,在 ios4.1 模拟器和运行 os4.1 的 3GS iphone 上)从附件类型无切换到附件类型复选标记图像绘制在不透明的白色背景而不是透明背景上。相反,如果我重新加载表格(其中还为每个单元格设置了适当的附件类型),透明度 100% 的时间都可以正常工作。

这是一个错误吗?还是修改 tableView:didSelectRowAtIndexPath: 中的单元格不是正确的做法,而应该重新加载该行?还是我还缺少其他东西?

编辑:这是我的 didSelectRowAtIndexPath 代码,显示了不良行为:

编辑 2:关于正在发生的事情的更多细节。问题发生在取消选择动画的最后。当取消选择动画正在运行并且蓝色选择逐渐消失时,复选标记会出现并正确透明地显示。在取消选择动画完成并且蓝色全部消失后,可能在选择颜色完全消失后的 1/10 秒内,复选标记附件“自动”变为不透明且无需用户进一步输入。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
    if ( self.editing )
    
    
    else 
    
        [self.myTableView deselectRowAtIndexPath:indexPath animated:YES];
        UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath];

        // toggle the selection status of the selected row
        //
        NSNumber *rowObj = [NSNumber numberWithUnsignedInt:indexPath.row];
        if ( [self.selectedRows containsObject:rowObj] )
        
            // currently selected, now de-select
            //
            cell.accessoryType = UITableViewCellAccessoryNone;
            [self.selectedRows removeObject:rowObj];
        
        else 
        
            // currently unselected, now select
            //
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
            [self.selectedRows addObject:rowObj];
        
    

【问题讨论】:

ok 发布了 didSelectRowAtIndexPath ("broken") 代码。如果我注释掉 cell.accessoryType 行并在底部添加 [tableView reload] 则透明度始终有效。 正在通过手动调用 [self.myTableView cellForRowAtIndexPath:indexPath] 修改单元格;完全是假的?我在网上的一些代码中看到了它(“所以它一定是真的!”)并复制了它。是否有任何保证 UITableView 尊重以这种方式完成的单元格更改?根据我所看到的,答案似乎是“不一定”...... 【参考方案1】:

我认为如果您将 toogle 选择 段代码移动到

会更干净
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

并在 didSelectRowAtIndexPath 调用

[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

这样一来,您将只重新加载选定的行,而无需调用 reloadData. 希望这会有所帮助!

【讨论】:

【参考方案2】:

这篇文章已经 4 个月没有更新了,但我想我会提交我的解决方案,因为它似乎可以工作并且可以帮助其他有类似问题的人。

一切都发生在 didSelectRowAtIndexPath 方法中。我调用的 self.view 是一个 tableView(所以用你的 tableView 的名称替换它,例如 self.tableView)

// let's go through all the cells to update them as I only want one cell at a time to have the checkmark next to it
for (int i=0; i<[self.detailsArray count]; i++) 
    // whenever we reach the cell we have selected, let's change its accessoryType and its colour
    if (i == indexPath.row) 
        // that's the row we have selected, let's update its 
        UITableViewCell *cell = [self.view cellForRowAtIndexPath:indexPath];
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
        cell.textLabel.textColor = [UIColor colorWithRed:51.0f/255.0f green:102.0f/255.0f blue:153.0f/255.0f alpha:1.0f];
    
    // if it isn't the cell we have selected, let's change it back to boring dark colour and no accessoryType
    else 
        UITableViewCell *cell = [self.view cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
        cell.accessoryType = UITableViewCellAccessoryNone;
        cell.textLabel.textColor = [UIColor darkTextColor];
    


// don't forget to deselect the row
[self.view deselectRowAtIndexPath:indexPath animated:YES];

【讨论】:

我没有用最近的 sdks 重新检查场景,也许我在自我回答中注意到的情况已经修复,但请注意,我发现在 didSelectRowAtIndexPath 中更新表行时出现故障,除非选择样式是 UITableViewCellSelectionStyleNone。我还注意到您在视觉更改之后调用 deselectRowAtIndexPath:animated:,而我之前调用它。 是的,你对 UITableViewCellSelectionStyleNone 是正确的,我确实必须将我的单元格更改为这种样式才能更新:) 至于 deselectRowAtIndexPath:你可以把它放在任何地方,它不会改变任何东西。【参考方案3】:

这个 UITableViewDelegate 方法:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

在显示单元格之前调用。在那里修改您的附件视图应该可以工作。

【讨论】:

感谢您的消息,鲍勃,但我看不出您的回答对我有什么帮助。正如我所写,我总是可以调用 [theTableView reloadData] 来获得正确的操作,因为我的 cellForRowAtIndexPath 正确分配了附件。我的问题是:我可以在选择时更改单元格并期望单元格正确更新吗?请注意,当我在 didSelectRowAtIndexPath 中更改附件 did 时,它发生了变化,但出现了与透明度相关的可见“故障”。我需要解决这两点之一。【参考方案4】:

在使用自定义表格行选择动画调试不相关项目中的另一个问题时,我发现如果单元格选择样式不是 UITableViewCellSelectionStyleNone,那么在 didSelectRowAtIndexPath 中对单元格执行的任何更改都会出现故障和其他理想结果(对单元格 N 所做的更改直到稍后选择单元格 != N 才会显示,并且在单元格上执行的动画根本不会显示)。当我将选择样式更改为 UITableViewCellSelectionStyleNone 时,在 didSelectRowAtIndexPath 中所做的所有可视单元格更改都会立即显示出来而不会出现问题。

【讨论】:

以上是关于在 tableView 中修改 UITableViewCell 附件类型时出现问题:didSelectRowAtIndexPath:的主要内容,如果未能解决你的问题,请参考以下文章

展开和折叠 tableview 单元格

在tableview中加载异步图像,它们在每次滚动时消失

了解 tableView 等函数中的 Swift 参数表示法

tableView计算动态行高的总结

IOS7上的Tableview字幕

UITableView dataSource 必须从 tableView:cellForRowAtIndexPath 返回一个单元格: