UITableView flickers with UIRefreshControl

I have a UITableView with a UIRefreshControl defined inside the viewDidLoad: method for a UIViewController , as shown below:

 - (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]; } 

I use a cell to determine the size of the cell to update the cell data. When reloading data, the UITableView flickers. Is there any way to avoid this?

Edit I linked the video file to demonstrate an example. UITableView flickers when reloading data. I am using autolayout to update dynamic cell heights.

Here is a sample that can recreate this problem. UITableView needs to be pulled for updating. The table view is reloaded in the main queue. The camera is changed using auto power off.


+8
ios objective-c uitableview uiviewcontroller uirefreshcontrol
source share
6 answers

I assume the problem is using the evaluation Height and UITableViewAutomaticDimension, as well as the reloadData uitableview. This is reported here.

Delay will work, but its not the right way to achieve it if you don't want the hacking work to work.

+1
source share

Today I have the same problem and I managed to solve the problem using CATransaction, here is the code snippet in Swift, executed in 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() 
+10
source share

The problem is that you call -reloadData and -endRefreshing together. Both want to update the view. You need to separate them a little.

One of these options will work, depending on where you want to see the cell update:

 [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]; 

You probably need less delay with the first option. It seems like 0.0 seconds works in your code example. This is enough to get the -endRefreshing animation on the next screen.

+4
source share
 -(void)refreshMessages{ self.messages = [NSMutableArray new]; [self loadData]; [self.tableView reloadData]; [self.refreshControl endRefreshing]; } 
0
source share

Maybe calling reloadData and endRefreshing could cause a flicker to happen, so I changed your code a bit and deleted the send block, which cleared of clicking

 - (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]; // }); } 
0
source share

You tried?

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

instead:

 [self.messagesTableView reloadData]; 
0
source share

All Articles