【问题标题】:UITableView reload sectionUITableView 重载部分
【发布时间】:2012-01-08 13:24:07
【问题描述】:

我只想重新加载一个部分而不是整个表格。 UITableView有什么方法吗。

[tableView reloadData] 用于加载全表。
我想知道如何只加载一个部分,因为我的表中有大量行。

【问题讨论】:

标签: iphone uitableview


【解决方案1】:

是的,有:

- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation

【讨论】:

    【解决方案2】:

    你需要这个...用于重新加载行

    - (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
    

    或用于重新加载部分

    - (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation
    

    【讨论】:

      【解决方案3】:

      reloadSections 方法困扰着我——因为我必须构造一些对象。如果您需要灵活性,这很好,但有时我也只想要简单性。它是这样的:

      NSRange range = NSMakeRange(0, 1);
      NSIndexSet *section = [NSIndexSet indexSetWithIndexesInRange:range];                                     
      [self.tableView reloadSections:section withRowAnimation:UITableViewRowAnimationNone];
      

      这将重新加载第一部分。我更喜欢在 UITableView 上有一个类别,然后调用这个方法:

      [self.tableView reloadSectionDU:0 withRowAnimation:UITableViewRowAnimationNone];
      

      我的分类方法是这样的:

      @implementation UITableView (DUExtensions)
      
      - (void) reloadSectionDU:(NSInteger)section withRowAnimation:(UITableViewRowAnimation)rowAnimation {
          NSRange range = NSMakeRange(section, 1);
          NSIndexSet *sectionToReload = [NSIndexSet indexSetWithIndexesInRange:range];                                     
          [self reloadSections:sectionToReload withRowAnimation:rowAnimation];
      }
      

      【讨论】:

      • 喜欢@implementation 函数!感谢您让事情变得如此简单
      • 调用 [NSIndexSet indexSetWithIndex:section] 不是更容易吗?
      • 或者你可以做[NSIndexSet indexSetWithIndex:1](而不是范围)
      【解决方案4】:

      但您只能重新加载包含相同行数的部分 (或者您必须手动添加或删除它们)。否则你会得到:

      *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 2. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (0), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'

      当您使用[tableView reloadData] 时不需要。

      当您需要重新加载一个部分并且您更改了其中的行数时,您可以使用以下内容:

      NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:section];
      
      [self beginUpdates];
          [self deleteSections:indexSet withRowAnimation:rowAnimation];
          [self insertSections:indexSet withRowAnimation:rowAnimation];
      [self endUpdates];
      

      如果你把它放在一个类别中(比如 bandejapaisa 节目),它可能看起来像这样:

      - (void)reloadSection:(NSInteger)section withRowAnimation:(UITableViewRowAnimation)rowAnimation {
          NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:section];
      
          [self beginUpdates];
              [self deleteSections:indexSet withRowAnimation:rowAnimation];
              [self insertSections:indexSet withRowAnimation:rowAnimation];
          [self endUpdates];
      }
      

      【讨论】:

      • 在什么情况下?现在更好的方法可能是使用 KVO(从而接收基于对某些模型的更改自动重新加载 UITableView 的可能性) - 或者如果您使用 CoreData,您可能对 NSFetchResultsController 感兴趣。
      • 我遇到了这个问题。我只是在重新加载实际部分之前重新加载有问题的部分。它解决了问题。
      【解决方案5】:

      根据此处接受的答案,我制作了一个函数,该函数将使用动画重新加载表格中的所有部分。这可以通过仅重新加载可见部分来优化。

      [self.tableView reloadData];
      NSRange range = NSMakeRange(0, [self numberOfSectionsInTableView:self.tableView]);
      NSIndexSet *sections = [NSIndexSet indexSetWithIndexesInRange:range];
      [self.tableView reloadSections:sections withRowAnimation:UITableViewRowAnimationFade];
      

      在我的例子中,我不得不在部分动画之前强制 reloadData,因为表的基础数据已经改变。但是它的动画效果很好。

      【讨论】:

        【解决方案6】:

        尝试使用

        [self.tableView beginUpdates]; 
        [self.tableView endUpdates];
        

        希望这能解决您的问题。

        【讨论】:

          【解决方案7】:

          如果您有自定义剖面视图,您可以在视图控制器中添加对它的弱引用,并随时更新它。这是我的参考代码:

          @property (weak, nonatomic) UILabel *tableHeaderLabel;
          
          ....
          
          -(UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
          {
              UITableViewHeaderFooterView *myHeader = [[UITableViewHeaderFooterView alloc] init];
          
              UILabel *titleLabel = [[UILabel alloc] init];
              [titleLabel setFrame:CGRectMake(20, 0, 280, 20)];
              [titleLabel setTextAlignment:NSTextAlignmentRight];
              [titleLabel setBackgroundColor:[UIColor clearColor]];
              [titleLabel setFont:[UIFont systemFontOfSize:12]];
          
              [myHeader addSubview:titleLabel];
          
              self.tableHeaderLabel = titleLabel; //save reference so we can update the header later
          
              return myHeader;
          }
          

          然后你可以像这样更新你的部分:

          - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
          {
              self.tableHeaderLabel.text = [NSString stringWithFormat:@"Showing row: %ld", indexPath.row];
          }
          

          【讨论】:

            【解决方案8】:

            正确的方法:

            [self.tableView beginUpdates]; 
            [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
            [self.tableView endUpdates];
            

            【讨论】:

              【解决方案9】:

              这里是方法,你可以通过不同的方式传递section details

              [self.tableView reloadSections:[[NSIndexSet alloc] initWithIndex:1] withRowAnimation:NO];
              
              [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationNone];
              

              重新加载特定部分可以提高表格视图的性能,有时它还可以避免一些问题,例如在视图中浮动/移动自定义页眉页脚。所以尽可能尝试使用 reloadSection 而不是 relaodData

              【讨论】:

                【解决方案10】:

                对于 Swift 3、4 和 5

                let sectionToReload = 1
                let indexSet: IndexSet = [sectionToReload]
                
                self.tableView.reloadSections(indexSet, with: .automatic)
                

                【讨论】:

                  【解决方案11】:

                  但您只能重新加载包含相同行数的部分(或者您必须手动添加或删除它们)。否则你会得到一个 NSInternalInconsistencyException。

                  步骤:

                  1. 计算要删除和/或插入哪些行
                  2. 根据这些生成一个 IndexPath 数组
                  3. 调用相关的tableView方法

                  现在您可以安全地调用 reloadSections :) Reload 部分将为其余索引调用更新。

                  或者您可以使用类似的库:https://github.com/onmyway133/DeepDiff

                  Swift 伪代码:

                  
                          tableView.deleteRows(at: valueIndexesToRemove, with: .automatic)
                          tableView.insertRows(at: valueIndexesToInsert, with: .automatic)
                          tableView.reloadSections(IndexSet([section]), with: .automatic)
                  
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多