iPhone UITableView单元格保持选中

45

在我的UITableView中有时候触摸后单元格仍然保持选中状态。由于它只偶尔发生,我无法重现这个问题。

有什么提示吗?也许与tableView的释放不当有关?

    - (void)tableView:(UITableView *)tableView 
    didSelectRowAtIndexPath:(NSIndexPath *)indexPath{   
    NSUInteger row = [indexPath row];

    [tableView deselectRowAtIndexPath:indexPath animated:YES];

switch (row) {
    case 0:
        FruitViewController *fruitController = [FruitViewController alloc];
        [fruitController retain];
        [fruitController initWithNibName:@"FruitView" bundle:[NSBundle mainBundle]];
        [self.navigationController pushViewController:fruitController animated:YES];
        [fruitController release];
        break;
    case 1: 
        CerealsViewController *cerealsController = [CerealsViewController alloc];
        [cerealsController retain];
        [cerealsController initWithNibName:@"CerealsView" bundle:[NSBundle mainBundle]];
        [self.navigationController pushViewController:cerealsController animated:YES];
        [cerealsController release];
        break;
    default:
        break;   
}
   }

3
你可能在重写viewWillAppear:animated方法时没有调用[super viewWillAppear:animated]吗? - Tieme
7个回答

96

我不知道为什么你会遇到这个问题,但以下是一些修复建议:

根据苹果的 HIG(Human Interface Guidelines),选择应该在返回之前的视图控制器上被保留,直到从堆栈中推送的视图控制器返回。如果你的控制器只是一个 UITableViewController,则在返回到视图时应自动取消选中。如果不是,请添加以下代码:

- (void) viewWillAppear:(BOOL)animated {
    [tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:animated];
    [super viewWillAppear:animated];
}

在视图控制器中的某个位置。

如果有些行在被点击时不会进入另一个视图,并且实际上在被选择时也不做任何事情,那么它们不应该是可选的。因此,您可以在其中覆盖:

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath

在不应该选择行的情况下,返回nil


21

一个可能的原因是在扩展UITableViewController的控制器中重写了-viewWillAppear:animated:方法却没有调用[super viewWillAppear]。在-viewWillAppear方法的开头添加[super viewWillAppear:animated]可能会纠正这个问题。


10

为了补充"Ed Marty"的回答,我选择在"viewWillDisappear"方法中添加取消选择,因为我认为这样看起来更好。

此外,我正在使用带有普通UIViewController的UITableView(而不是UITableViewController),所以tableView变量对我不可用。为了解决这个问题,我在我的视图控制器头文件中添加了一个tableView属性(在我的XIB文件中,我将实际的tableView连接到该属性)...

@property (nonatomic,retain) IBOutlet UITableView *tableView

...并在视图控制器的实现中连接了该属性并执行了以下取消选择操作..

@synthesize tableView

- (void) viewWillDisappear:(BOOL)animated {
    [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:animated];
    [super viewWillDisappear:animated];
}

谢谢,IBOutlet 的信息对我很有帮助。 - Tom Redman
这个解决方案是最好的,因为所选答案在导航控制器中不起作用。 - codingrhythm

8
如果您正在使用UITableViewController,则可以使用以下方法:
self.clearsSelectionOnViewWillAppear = YES;

我应该把这放在哪里? - Gajendra K Chauhan
尝试在您的viewDidLoad或ViewWillAppear中使用它 @GajendraKChauhan - Pach
@VanDuTran,你是如何实现你的视图控制器的?通过nib还是storyboard?你能否尝试从-(void)awakeFromNib开始实现吗?因为当你在xcode中创建一个主细节示例项目时,你会看到一些由Apple在awakeFromNib中生成的代码,'self.clearsSelectionOnViewWillAppear = NO',所以它应该可以工作。 - Liangjun
我使用Storyboard和Table View Controller对象。它生成了代码self.clearsSelectionOnViewWillAppear,我将其更改为YES。当您呈现/解除视图控制器时,它可以正常工作。但是,当您点击将您带到另一个应用程序(例如:Safari)的单元格,然后返回时,它不起作用。 - Van Du Tran
@VanDuTran 然后检查上面的答案,尝试在didSelectRowatIndexPath中取消选定行
  • (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // 转到Safari或其他应用程序 [tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:NO];
}
- Pach

4
在我的情况下,我取消选择了didSelectRowAtIndexPath中最后一个单元格:
  - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    // Do smth here. segue ..etc

    [tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:NO];
}

0

在你的UITableViewCell类中使用这种方法

(void)setSelected:(BOOL)selected animated:(BOOL)animated {

// Just comment This line of code

// [super setSelected:selected animated:animated];

}

甚至你可以在didSelectRowAtIndexPath方法中尝试这段代码:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
 
  // 当行被选中时执行一些操作

[tableView deselectRowAtIndexPath:indexPath animated:YES];

}


0

一旦你学会了如何管理表格,解决这个问题只需要大约两秒钟。

一旦单元格滚动出屏幕,它们就会失去格式。 表格通过关闭其他单元格并在用户滚动回来时重新创建它们来最小化内存使用。

即使是像重新加载表格数据这样的事情,也只适用于此刻屏幕上的单元格。重点是,cellForRowAtIndexPath 可能会创建相同的单元格五次,而用户从未点击按钮或离开视图控制器!因此,设置它以重新加载任何格式。在 cellForRowAtIndexPath 中添加类似以下内容:

    if arrayOf_SelectedCells.contains(indexPath) {
        setup_Selected(cell)
        //Where setup_Selected is a custom function to apply formatt
    } else {
        setup_Unselected(cell)
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接