Iphone UITableView,在选择时更换附件时出现问题

Iphone UITableView,在选择时更换附件时出现问题,iphone,objective-c,uitableview,Iphone,Objective C,Uitableview,我正在使用UITableView来允许选择一个(多个)项目。与选择铃声时的UI类似,我希望选中项目,而不选中其他项目。我希望在触摸时选择单元格,然后将其设置为正常颜色(同样,与铃声选择界面类似) UIViewController子类是我的表的委托和数据源(不是UITableViewController,因为我在其中还有一个工具栏) 我正在设置CellForRowatineXpath:中单元格的accessoryType,并在DidSelectRowatineXpath:中选择单元格时更新模型。我

我正在使用UITableView来允许选择一个(多个)项目。与选择铃声时的UI类似,我希望选中项目,而不选中其他项目。我希望在触摸时选择单元格,然后将其设置为正常颜色(同样,与铃声选择界面类似)

UIViewController子类是我的表的委托和数据源(不是UITableViewController,因为我在其中还有一个工具栏)

我正在设置CellForRowatineXpath:中单元格的accessoryType,并在DidSelectRowatineXpath:中选择单元格时更新模型。我能想到的将所选单元格设置为选中标记(并清除上一个)的唯一方法是在didSelectRowAtIndexPath:中调用[tableView reloadData]。但是,当我这样做时,单元格取消选择的动画效果很奇怪(单元格标签应该在的位置会出现一个白色框)。当然,如果我不调用reloadData,accessoryType不会更改,因此不会出现复选标记

我想我可以关闭动画,但这似乎是站不住脚的。我还在didSelectRowAtIndexPath:中尝试获取和改变细胞,但这是一个巨大的痛苦

有什么想法吗?缩写代码如下

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell* aCell = [tableView dequeueReusableCellWithIdentifier:kImageCell];
    if( aCell == nil ) {
        aCell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:kImageCell];
    }

    aCell.text = [imageNames objectAtIndex:[indexPath row]];
    if( [indexPath row] == selectedImage ) {
        aCell.accessoryType = UITableViewCellAccessoryCheckmark;
    } else {
        aCell.accessoryType = UITableViewCellAccessoryNone;
    }
    return aCell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    selectedImage = [indexPath row]
    [tableView reloadData];
}

我遇到了完全相同的问题,但从未解决过

最后,这对我来说是没有意义的,因为我必须倾听模型中的更改(如果连接丢失,选择可能会随着用户的控制而改变),所以我只是更改了模型,让通知重新加载数据,但它看起来不太漂亮(这就像一个非动画取消选择,但一次运行循环迭代延迟!)

我怀疑唯一的方法是,正如你所建议的,保留对单元格本身的引用缓存。如果您编写一个UITableViewCell子类来封装逻辑,重写-prepareforuse,这应该不会太混乱

不过,这并不漂亮,如果苹果公司的铃声人员不得不这样做,他们应该更努力地敦促UITableView团队解决这个问题

编辑:


你知道什么?!这毕竟很容易-[UITableView CellForRowatineXpath]将为您提供实际的单元格(如果它们在屏幕外,则为零),您只需更改附件类型。

我按照哈芬奇在编辑中的建议解决了这个问题。我的代码示例确保只检查了一行,但我确信如果这不是您需要的,您可以调整它

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

int newRow = [indexPath row];
int oldRow = [lastIndexPath row];

if (newRow != oldRow)
{
    UITableViewCell *newCell = [tableView cellForRowAtIndexPath:
                                indexPath];
    newCell.accessoryType = UITableViewCellAccessoryCheckmark;

    UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:
                                lastIndexPath];
    oldCell.accessoryType = UITableViewCellAccessoryNone;

    lastIndexPath = indexPath;
}

[tableView deselectRowAtIndexPath:indexPath animated:YES];
}

我有一个更干净的方法

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

    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

    if (cell.accessoryType == UITableViewCellAccessoryNone) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;

    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }
}

这将按需要工作

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


int newRow = [indexPath row];
int oldRow = [lastIndexPath row];


if (newRow == oldRow){
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

    if (cell.accessoryType == UITableViewCellAccessoryNone) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;

    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }

     lastIndexPath = indexPath;
}


if (newRow != oldRow)
{
    UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
    newCell.accessoryType = UITableViewCellAccessoryCheckmark;

    UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:lastIndexPath];
    oldCell.accessoryType = UITableViewCellAccessoryNone;

    lastIndexPath = indexPath;
}


[tableView deselectRowAtIndexPath:indexPath animated:YES];

}

我使用这个简单而好的工作机制来处理重载rowsatindexpath

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSArray *rowsArray = [NSArray arrayWithObjects:indexPath, selectedIndexPath, nil];
    self.selectedIndexPath = indexPath;

    [tableView reloadRowsAtIndexPaths:rowsArray withRowAnimation:UITableViewRowAnimationNone];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    .... skipped usual code .....

    if ([selectedIndexPath compare:indexPath] == NSOrderedSame) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }
    return cell;
}

我已经放弃并关闭了动画,但哈芬奇的编辑评论起了作用。我以前曾尝试过这个解决方案,但取消选中其他单元格很麻烦。我没有想到缓存以前选择的单元格路径,就像Ron Srebo的回答一样。谢谢你们两位。哦,你们将如何从以前选择的单元格中删除复选标记?这完全解决了我的问题。非常感谢。只需在didSelectRowAtIndexPath委托中这样写。[tableView取消行索引路径:indexPath动画:是];和[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section]withRowAnimation:UITableViewRowAnimationAutomatic];
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{
    UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:index];
    oldCell.accessoryType = UITableViewCellAccessoryNone;
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
    index = indexPath;  
}