【问题标题】:Why does UITableViewCell remain highlighted?为什么 UITableViewCell 仍然突出显示?
【发布时间】:2010-12-22 20:58:59
【问题描述】:

什么会导致表格视图单元格在被触​​摸后保持突出显示?我单击单元格,可以看到它在推送详细视图时保持突出显示。弹出详细视图后,单元格仍会突出显示。

【问题讨论】:

    标签: ios uitableview cocoa-touch


    【解决方案1】:

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

    因此,无论您在 didSelectRowAtIndexPath 中执行的其他操作,您只需调用 deselectRowAtIndexPath 即可。

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

    【讨论】:

    • 我更喜欢在 viewDidAppear 中调用deselectRowAtIndexPath,如果选择该行会打开一个新视图。
    • 实际上这不是正确的称呼,真的...尝试使用带有表格的Apple应用程序(联系人是一个很好的应用程序),然后您会在推出新屏幕后看到,返回时,单元格在被取消选择之前仍会短暂突出显示。从理论上讲,我认为您不必做任何额外的工作就可以立即取消选择它,因此不需要 viewDidAppear 中的代码...
    • @Kendall, @4thSpace:也许我最后的评论对我指的是谁感到困惑,对此深表歉意。 UITableViewController 从-viewDidAppear 调用其tableView 属性上的-deselectRowAtIndexPath:animated: 方法。但是,如果您在 UIViewController 子类中有一个表格视图,您应该自己从-viewDidAppear 调用-deselectRowAtIndexPath:animated:。 :)
    • 在我的 UITableViewController 子类中,它实际上是对 -viewWillAppear: 的覆盖,它破坏了它。添加对[super viewWillAppear:animated] 的调用使其再次工作。
    • 自 3.2 起,如果您的 UITableViewController 的 clearsSelectionOnViewWillAppear 属性设置为 YES(这是默认值),并且您没有阻止 [super viewWillAppear]被调用。
    【解决方案2】:

    最干净的方法是在 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

    Swift 版本

    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)
        }
    }
    

    【讨论】:

    • 如果大多数人不使用 UITableViewController,我希望这是他们想要的。 +1
    • 我想知道现在人们在做什么,因为 iOS 7 允许用户“拖”回来。部分拖动但未完成操作将触发 viewWillAppear。当用户真实返回时,该行不会被选中。
    • @BenPackard 只需在 viewDidAppear 上调用它。
    • @Jessica indexPathForSelectedRow 调用可以返回 nil,因此应该检查它。 The documentation states:标识所选行的行和节索引的索引路径,如果索引路径无效,则为 nil。
    • 这应该被标记为接受的答案,它对用户界面更友好,所以用户可以在返回后进行选择,完美?
    【解决方案3】:

    对于 Swift 用户,请将其添加到您的代码中:

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

    这是 paulthenerd 的回答,但在 Swift 而不是 Obj-C 中。

    【讨论】:

    • 不是自己取消选中的吗,我是说你放手的那一刻?
    • @Honey 在以前的 iOS 版本中可能是这样,或者在视图消失时,但现在在 iOS 10(可能甚至更早)及更高版本中肯定不会。
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      Swift 3 解决方案

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

      【讨论】:

        【解决方案6】:

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

        - (void)setSelected:(BOOL)selected animated:(BOOL)animated
        {
        
         // [super setSelected:selected animated:animated];
        
        }
        

        希望这会有所帮助。

        【讨论】:

          【解决方案7】:

          使用 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,您还可以利用属性clearsSelectionOnViewWillAppear。

          【讨论】:

            【解决方案8】:

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

            查看默认 Apple 模板中新 UITableViewController 子类的注释:

            - (void)viewDidLoad
            {
                [super viewDidLoad];
            
                // Uncomment the following line to preserve selection between presentations.
                // self.clearsSelectionOnViewWillAppear = NO;
            }
            

            【讨论】:

              【解决方案9】:

              Swift 5 解决方案:

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

              【讨论】:

                【解决方案10】:

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

                我的问题是 VC 是一个 UIViewController(包含一个包含 TableView 的 View)。相反,我使 VC 成为 UITableViewController(包含 TableView)。 UITableViewController 类在从推送返回后自动处理取消突出显示的表格单元格。帖子“Issue with deselectRowAtIndexPath in tableView”的第二个回答对这个问题给出了更完整的答案。

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

                【讨论】:

                  【解决方案11】:

                  如果这些都不适合您,请考虑以下解决方法:

                  使用 unwind segue 调用:

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

                  为什么要这样做?主要是如果您无法在正确的时间运行取消选择代码。我在 viewWillAppear 上无法正常工作时遇到了麻烦,因此展开效果要好得多。

                  步骤:

                  1. 将 unwind segue(或从上方粘贴)写入您的第一个 VC(有表格的那个)

                  2. 转到第二个 VC。从您用于关闭该 VC 的 Cancel/Done/Etc 按钮按住 Control 并拖动到顶部的退出图标。

                  3. 选择您在第 1 步中创建的展开转场

                    祝你好运。

                  【讨论】:

                  • 这是 viewDidAppear 不触发时的最佳解决方案(即,如果子视图以模态方式呈现为表单并且不覆盖整个屏幕)。
                  【解决方案12】:

                  我正在使用 CoreData,所以对我有用的代码是 Swift 中各种答案的想法的组合:

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

                  【讨论】:

                    【解决方案13】:
                     func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
                        tableView.deselectRow(at: indexPath as IndexPath, animated: true)
                    }
                    

                    【讨论】:

                      【解决方案14】:

                      我已经有同样的问题很长时间了,所以以防万一其他人在苦苦挣扎:

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

                      这应该会在出现时为您的表格提供预期的“淡入淡出选定行”。

                      【讨论】:

                        【解决方案15】:

                        在 UITableViewCell 类中使用该方法

                        - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
                        
                           // Just comment This line of code
                           // [super setSelected:selected animated:animated];        
                        }
                        

                        【讨论】:

                          【解决方案16】:

                          对于 Swift 3: 我希望它在 viewDidDisappear 中使用

                          定义:-

                              var selectedIndexPath = IndexPath()
                          

                          在 viewDidDisappear 中:-

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

                          在 didSelectRowAtIndexPath:-

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

                          【讨论】:

                            【解决方案17】:

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

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

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

                            }

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

                            // MARK: UITableViewDelegate

                            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()
                              }
                            } 
                            

                            【讨论】:

                              【解决方案18】:

                              Xcode 10,斯威夫特 4

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

                              问题函数

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

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

                              【讨论】:

                                猜你喜欢
                                • 1970-01-01
                                • 1970-01-01
                                • 2011-07-28
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 2012-10-03
                                • 1970-01-01
                                相关资源
                                最近更新 更多