UITableView与UIRefreshControl闪烁问题

10

我有一个UITableView,在UIViewControllerviewDidLoad:方法中定义了UIRefreshControl,如下所示:

- (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 会闪烁。有没有办法避免这种情况?


1
你有一个 'UIViewController' 还是一个 'UITableViewController'?在 viewDidLoad 中初始化 'tableViewController' 对象后,你会在哪里呈现它?你应该提供更多信息,这将有助于解决问题。 - croX
这只是一个猜测,但你尝试过[tableView beginUpdates/endUpdates]了吗? - Mert Buran
7个回答

12

今天我遇到了同样的问题,并使用CATransaction解决了它,这里是Swift中的一小段代码片段,在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()

我曾经遇到过类似的闪烁问题,当在表视图底部附近添加新行并从顶部删除行时会出现此问题。通过使用 CATransaction.begin() ... CATransaction.setDisableActions(true) ... tableView.beginUpdates() ... do the updates ... tableView.endUpdate() ... CATransaction.commit() 方法解决了这个问题。 - brki

6
问题在于你同时调用了 -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动画。


4

Swift

你可能想使用Swift编程语言

extendedLayoutIncludesOpaqueBars = true

为了使UIRefreshControl动画正确,您需要在您的ViewController中进行设置。


2

我猜问题出在使用estimatedHeight和UITableViewAutomaticDimension与uitableview的reloadData一起使用。这个问题已经在这里报告过了:here

虽然延迟可以解决问题,但这并不是正确的方法,除非你想要一个hackish的解决方法。


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

请阅读"[answer]"和"完全基于代码的答案解释"。如果您能提供为什么这是首选解决方案以及解释其工作原理的说明,那将更有帮助。我们想要教育,而不仅仅是提供代码。 - the Tin Man

0

可能是调用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];
//    });

}

0

你试过了吗?

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

改为:

[self.messagesTableView reloadData];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接