为什么 UITableViewCell 仍然突出显示?

什么会导致一个表格视图单元格在被触摸后仍然高亮显示?我点击单元格,可以看到它保持突出显示的细节视图被推。一旦弹出详细信息视图,单元格仍然高亮显示。

65542 次浏览

didSelectRowAtIndexPath中,您需要调用 deselectRowAtIndexPath来取消选择单元格。

所以无论你在 didSelectRowAtIndexPath中做什么,你只需要让它也调用 deselectRowAtIndexPath

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Do some stuff when the row is selected
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}

您是否子类化了 -(void)viewWillAppear:(BOOL)animated? 当您不在自定义方法中调用 [super viewWillAppear:animated];时,选中的 UITableViewCell 不会取消选择。

我在我的向下钻取应用程序中也遇到了这个问题。在一个视图控制器(我称之为 VC)按下另一个视图控制器后返回,VC 中选择的单元格仍然突出显示。在我的应用程序中,我创建了 VC 来处理我向下钻取的第二层(三层中的第二层)。

我的问题是 VC 是一个 UIViewController (包含一个包含 TableView 的视图)。相反,我把 VC 变成了 UITableViewController (包含 TableView)。UITableViewController 类在从推送返回之后自动处理表单元格的去突出显示。对于“ TableView 中 deselectRowAtIndexPath 的问题”这篇文章的第二个回答对这个问题给出了一个更完整的答案。

根视图控制器没有出现问题,因为当我在 XCode 中将应用程序创建为“基于导航的应用程序”时,生成的根视图控制器已经被创建为子类 UITableViewController。

要获得 Kendall Helmstetter Gelner 在他的评论中描述的行为,您可能不希望 deselectRowAtIndexPath,而是希望控制器上的 clearsSelectionOnViewWillAppear 属性。也许这是偶然设置为 YES 的?

参见 Apple 默认模板中新 UITableViewController 子类的注释:

- (void)viewDidLoad
{
[super viewDidLoad];


// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
}

如果使用 UITableViewCell,请注释以下行

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


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


}

希望这个能帮上忙。

最干净的方法是在 viewWillAppear:

- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// Unselect the selected row if any
NSIndexPath*    selection = [self.tableView indexPathForSelectedRow];
if (selection) {
[self.tableView deselectRowAtIndexPath:selection animated:YES];
}
}

这样,当您返回到控制器时,就可以像应该的那样使所选内容淡出。

取自 http://forums.macrumors.com/showthread.php?t=577677

快速版

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)


// deselect the selected row if any
let selectedRow: IndexPath? = tableView.indexPathForSelectedRow
if let selectedRowNotNill = selectedRow {
tableView.deselectRow(at: selectedRowNotNill, animated: true)
}
}

长久以来,我一直有同样的问题,所以以防其他人遇到困难:

看一下你的 -tableView: cellForRowAtIndexPath:,看看你是在创建单元格还是在使用“重用标识符”。如果是后者,请确保 IB 中的表有一个具有该标识符的单元格。如果不使用重用标识符,只需为每一行创建一个新单元格。

然后,这应该给你的表预期的“淡出选定行”出现。

在 UITableViewCell 类中使用此方法

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


// Just comment This line of code
// [super setSelected:selected animated:animated];
}

对于 Swift 用户,请将以下代码添加到代码中:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}

这是 Paulthenerd 的回答,但是用 Swift 而不是 Obj-C。

如果这些都不适合你,考虑一下这个变通方法:

使用一个放松的接口呼叫:

@IBAction func unwind_ToTableVC (segue: UIStoryboardSegue) {
if let index = tableView.indexPathForSelectedRow {
tableView.deselectRowAtIndexPath(index, animated: true)
}
}

为什么要这么做?主要是如果您无法让取消选择的代码在正确的时间运行。我有麻烦,它不工作在视图 WillAppear 所以放松工作得更好。

步骤:

  1. 写一个放松的接口(或者从上面粘贴)到你的第一个 VC (有表格的那个)

  2. 去找第二越共。控件-从取消/完成/等按钮拖动,你正在使用解除该 VC 和拖动到退出图标在顶部。

  3. 选择您在步骤1中创建的放松接口

    祝你好运。

我使用的是 CoreData,所以对我有效的代码是来自不同答案的想法的组合,在 Swift:

override func viewDidAppear(_ animated: Bool) {
if let testSelected = yourTable.indexPathForSelectedRow {
yourTable.deselectRow(at: testSelected, animated: true)
}
super.viewDidAppear(true)
}

For Swift 3: 我更喜欢在 viewDid销声匿迹中使用它

定义:-

    var selectedIndexPath = IndexPath()

消失:-

    override func viewDidDisappear(_ animated: Bool) {
yourTableView.deselectRow(at: selectedIndexPath, animated: true)
}

在 did SelectRowAtIndexPath:-

    func tableView(_ tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) {
selectedIndexPath = indexPath
}

迅捷3解决方案

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
}

用 Swift 4更新

经过几次实验,也基于以前的答案,我得出结论,最好的行为可以通过两种方式实现: (在实践中几乎相同)

// First Solution: delegate of the table View
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
}


// Second Solution: With the life cycle of the view.
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)


let selectedRow: IndexPath? = tableView.indexPathForSelectedRow
if let selectedRow = selectedRow {
tableView.deselectRow(at: selectedRow, animated: false)
}
}

我个人采用了第一种解决方案,因为它简单明了。另一种可能性是,如果在返回 tableView 时需要一些动画,那么可以使用 viewWillAppear:

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)


let selectedRow: IndexPath? = _view.tableView.indexPathForSelectedRow
if let selectedRow = selectedRow {
_view.tableView.deselectRow(at: selectedRow, animated: true)
}
}

最后但同样重要的是,如果使用 UITableViewController,还可以利用属性 出现

 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
}

如果单元格在触摸后仍然高亮显示,则可以调用 UITabelView 方法,

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

`[tableView deselectRowAtIndexPath:indexPath animated:YES];`

}

或者,您可以使用以下方法,并根据您的要求进行修改,

//MARK: UITableViewgenerate

func tableView(tableView: UITableView, didHighlightRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.backgroundColor = UIColor.greenColor()
}
}


func tableView(tableView: UITableView, didUnhighlightRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.backgroundColor = UIColor.blackColor()
}
}

Xcode 10 Swift 4

我遇到了同样的问题,发现我在 tableViewController 的底部留下了一个 viewWillAppear 的空调。一旦我删除了空的覆盖函数,返回到 tableView 视图时该行不再保持突出显示。

问题函数

override func viewWillAppear(_ animated: Bool) {
// need to remove this function if not being used.
}

删除空函数解决了我的问题。

快速5解决方案:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
}