【问题标题】:UITableView Flickering with UIRefreshControlUITableView 闪烁与 UIRefreshControl
【发布时间】:2015-07-30 16:45:53
【问题描述】:

我在UIViewControllerviewDidLoad: 方法中定义了UITableViewUIRefreshControl,如下所示:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.refreshControl = [[UIRefreshControl alloc] init];
    [self.refreshControl addTarget:self action:@selector(refreshMessages) forControlEvents:UIControlEventValueChanged];
    UITableViewController *tableViewController = [[UITableViewController alloc] init];
    tableViewController.tableView = self.messagesTableView;
    tableViewController.refreshControl = self.refreshControl;  
}

- (void)refreshMessages {
    //load data items
    if ([self.refreshControl isRefreshing]) {
        [self.refreshControl endRefreshing];
    }

    [self.messagesTableView reloadData];
}

我使用自定尺寸单元格来更新单元格数据。重新加载数据时,UITableView 闪烁。有没有办法避免这种情况?

编辑 我已链接video 文件以获取示例演示。重新加载数据时的UITableView 闪烁。我使用自动布局来更新动态单元格高度。

这是一个sample 代码,可以重现此问题。 UITableView 应该被拉刷新。表视图重新加载到主队列中。正在使用自动布局调整单元格的大小。


【问题讨论】:

  • 那么你有'UIViewController'还是'UITableViewController'?你在哪里展示你在 viewDidLoad 中初始化的“tableViewController”对象?您应该提供更多信息,这会有所帮助
  • 只是在黑暗中拍摄,但您尝试过 [tableView beginUpdates/endUpdates] 吗?

标签: ios objective-c uitableview uiviewcontroller uirefreshcontrol


【解决方案1】:

斯威夫特

你可能想使用

extendedLayoutIncludesOpaqueBars = true

在您的 ViewController 中以获得正确的 UIRefreshControl 动画。

【讨论】:

    【解决方案2】:

    我今天遇到了同样的问题,我设法使用 CATransaction 解决了这个问题,这是 Swift 中的代码 sn-p,在 UITableViewController 中执行:

            CATransaction.begin()
            CATransaction.setCompletionBlock { () -> Void in
                /*wait for endRefreshing animation to complete 
                  before reloadData so table view does not flicker to top 
                  then continue endRefreshing animation */
    
                self.tableView.reloadData()
            }
    
            self.refreshControl!.endRefreshing()
            CATransaction.commit()
    

    【讨论】:

    • 我遇到了类似的闪烁问题,当靠近 tableview 的底部时,在底部添加了新行 并且从顶部删除了 行。使用CATransaction.begin() ... CATransaction.setDisableActions(true) ... tableView.beginUpdates() ... do the updates ... tableView.endUpdate() ... CATransaction.commit() 解决了这个问题
    【解决方案3】:

    我猜这个问题是使用estimatedHeight & UITableViewAutomaticDimension 以及uitableview 的reloadData。已举报here

    延迟是可行的,但它仍然不是实现它的正确方法,除非您想要解决问题。

    【讨论】:

      【解决方案4】:

      你试过了吗?

      [self.messagesTableView beginUpdates];
      [self.messagesTableView reloadSections:[NSIndexSet indexSetWithIndex:0/*target section*/]  withRowAnimation:UITableViewRowAnimationNone];
      [self.messagesTableView endUpdates];
      

      代替:

      [self.messagesTableView reloadData];
      

      【讨论】:

        【解决方案5】:

        可能调用reloadDataendRefreshing 可能会导致闪烁发生,所以我所做的是稍微修改了您的代码并删除了清除闪烁的调度块

        - (void)refreshMessages{
        
        self.messages = [NSMutableArray new];
        [self loadData];
        [self.tableView reloadData];
        [self.refreshControl performSelector:@selector(endRefreshing) withObject:nil afterDelay:0.5];
        
        
        //    double delayInSeconds = 0.5;
        //    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t) (delayInSeconds * NSEC_PER_SEC));
        //    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        //        [self.refreshControl endRefreshing];
        //    });
        
        }
        

        【讨论】:

          【解决方案6】:
          -(void)refreshMessages{
          
          self.messages = [NSMutableArray new];
          [self loadData];
          
          [self.tableView reloadData];
          [self.refreshControl endRefreshing];
          }
          

          【讨论】:

            【解决方案7】:

            问题是您同时调用 -reloadData 和 -endRefreshing。两者都想更新视图。您需要将它们分开一点。

            这些选项之一将起作用,具体取决于您希望在何处看到单元格更新:

            [self.tableView reloadData];
            [self.refreshControl performSelector:@selector(endRefreshing) withObject:nil afterDelay:0.5];
            
            [self.refreshControl endRefreshing];
            [self.tableView performSelector:@selector(reloadData) withObject:nil afterDelay:0.5];
            

            第一个选项可能需要更少的延迟。即使是 0.0 秒似乎也适用于您的示例代码。这足以在下一次屏幕刷新时获得 -endRefreshing 动画。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-11-01
              • 1970-01-01
              • 1970-01-01
              • 2012-04-05
              • 1970-01-01
              • 2016-03-19
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多