【问题标题】:Refresh only the custom header views in a UITableView?仅刷新 UITableView 中的自定义标题视图?
【发布时间】:2014-05-06 18:12:36
【问题描述】:

我的UITableView 在每个部分都有自定义UIView 标题。我只需要刷新标题而不是该部分中的其他内容。我已经尝试过 [self.tableView headerViewForSection:i] 并且它没有返回任何东西,即使它应该返回。无论如何我可以做到这一点吗?

编辑:基于新建议的代码

我也试了一下,它在该方法中调用/更新 UIView,但更改不会在视觉上传播到屏幕上。

for (int i = 0; i < self.objects.count; i++) {
    UIView *headerView = [self tableView:self.tableView viewForHeaderInSection:i];
    [headerView setNeedsDisplay];
}

【问题讨论】:

  • 您是使用 nib 加载标题,还是在 tableView:viewForHeaderInSection: 中以编程方式创建它们?
  • 我正在使用所述方法以编程方式创建它们。

标签: ios objective-c uitableview


【解决方案1】:

不要调用setNeedsDisplay,而是通过设置标题自己的属性来配置标题。当然,您必须获取表中的实际标题,不要调用委托方法,因为该方法通常会创建一个新的标题视图。

我通常使用从tableView:viewForHeaderInSection: 调用的小辅助方法来执行此操作。

例如:

- (void)configureHeader:(UITableViewHeaderFooterView *)header forSection:(NSInteger)section {
    // configure your header
    header.textLabel.text = ...
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UITableViewHeaderFooterView *header = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"Header"];
    [self configureHeader:header forSection:section];
}

- (void)reloadHeaders {
    for (NSInteger i = 0; i < [self numberOfSectionsInTableView:self.tableView]; i++) {
        UITableViewHeaderFooterView *header = [self.tableView headerViewForSection:i];
        [self configureHeader:header forSection:i];
    }
}

【讨论】:

  • 所有这些都很好,但是对UITableViewHeaderFooterView *header = [self.tableView headerViewForSection:i]; 的调用没有返回任何内容。我尝试做[self tableView:self.tableView viewForHeaderInSection:i],它返回一个标题并带我进行配置,但仍然没有在屏幕上直观地显示更改。
  • 如果[self.tableView headerViewForSection:i] 返回nil,那么您的tableView 没有此部分的标题,或者它当前不可见。当然[self tableView:self.tableView viewForHeaderInSection:i] 会返回一个视图,但是这个视图是新创建的,不是视图层次结构的一部分;你看不到那个视图。
  • 我该怎么做才能检查这个?从视觉上看,表格视图具有每个部分的标题,并且它们的实例化方式与您在上面编写的完全相同。
  • 我刚刚想通了。我已经设置了我的自定义类以返回 UIView 而不是 UITableViewHeaderFooterView。一旦我这样做了,一切都很好!你会建议每次在 viewForHeader/Footer 方法中返回一个 UITableViewHeaderFooterView 吗?
  • 当我的 tableview 重新加载或滚动 tableview 时,调用 tableview 标题。我在哪里做我的图像动画。但我想在点击导航栏按钮时做动画。而不是每次用户出现在这个屏幕上。我尝试上面的代码,但 viewforHeaderInSection 给我 nil 并且上面的代码不返回视图。
【解决方案2】:

为 headerView 创建您自己的 UIView 子类,并向其添加几个方法,以便您的视图控制器可以向其发送您想要的任何 UI 更新。

【讨论】:

    【解决方案3】:

    调用setNeedsDisplay 仅用于触发接收视图的drawRect: 方法。除非这是您的文本颜色逻辑所在的位置(即,在您用于标题视图的 UIView 子类的 drawRect 方法中),否则不会发生任何变化。您需要做的是直接在标题视图上调用某些内容以根据您的新数据或更改的数据更新它们的状态,或者直接访问标题视图中的标签并在迭代它们时自行更改。 setNeedsDisplay 只会触发在视图的drawRect: 方法中找到的代码。

    【讨论】:

      【解决方案4】:

      我最近遇到了这个确切的问题,只是通过在创建标头时保留指向标头的指针来克服它。我是在 Swift 中完成的,并且只使用了 swift 的字典类型,但是这个想法可以以某种方式被按摩到 objC 中。

        var headers : [ Int : UIView ] = [ : ] //dictionary for keeping pointer to headers
      
          override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
      
              if let h = super.tableView(tableView , viewForHeaderInSection: section) { //or create your view (this viewController inherits it)..
              self.headers.updateValue(h , forKey: section) //keep a pointer to it before you return it..
              return h
              }
              return nil
          }
      

      【讨论】:

        【解决方案5】:

        当您创建自定义标题视图时,使用UITableViewHeaderFooterView 而不是简单的UIView,当您初始化它时,使用如下内容:

        UITableViewHeaderFooterView *cell = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:@"reuseIdentifier"];
        

        reuseIdentifier 将告诉您的 UITableView 跟踪标头,当您尝试使用 [self.tableView headerViewForSection:i] 访问它时,它不应再返回 null

        您应该能够在进行修改后从headerViewForSection 返回的UITableViewHeaderFooterView 上使用setNeedsDisplay

        【讨论】:

          【解决方案6】:

          Swift 5解决方案:

          表格视图的委托方法:

          override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
              // Ideally, dequeue your header view...
              var view: UITableViewHeaderFooterView?
              if section == 0 { view = ... // dequeue appropriately
              } else if section == 1 { view = ... // dequeue appropriately
              } else ... // etc.
          
              setupHeaderView(&view)
              return view
          }
          

          在您想要更新标题视图的代码区域中:

          var headerView = tableView.headerView(forSection: i)
          setupHeaderView(&headerView)
          

          表头设置方法:

          func setupHeaderView(_ view: inout UITableViewHeaderFooterView?) {
              // do something with `view` here
          }
          

          【讨论】:

            【解决方案7】:

            【讨论】:

            • 这会重新加载整个第一部分(标题和单元格)——这不是问题所在。
            【解决方案8】:

            斯威夫特 5:

            如果您使用自定义视图作为表头视图,请尝试以下代码

            -- 将您的自定义类设为UITableViewHeaderFooterView 的子类。

            class MyCustomHeaderView : UITableViewHeaderFooterView {
                @IBOutlet weak var sampleLabel: UILabel!
             }
            

            -- 然后使用以下方法获取您的视图(使用节号)

            func updateHeaderView() {
            // This is for section no. 1, you can use `for loop` for all sections
            
             if let headerView = self.myTableView.headerView(forSection: 1) as? MyCustomHeaderView { 
               // Set values or update constraints to your view 
               headerView.sampleLabel.text = "your new text goes here"
               headerView.sizeToFit() //Resizes and moves the receiver view so it just encloses its subviews 
               self.myTableView.beginUpdates()
               self.myTableView.endUpdates() 
               // if you are using for loop then keep this `beginUpdates` and `endUpdates` outside loop
                }
             }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-08-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-11-26
              • 2011-04-25
              相关资源
              最近更新 更多