29

长时间的监听器,第一次调用堆栈溢出。要温柔。

我正在 UITableView 上实现 UIRefreshControl 以刷新表的数据。在其他下拉刷新实现中,刷新过程不会开始,直到用户的手指在拉动的刷新距离内抬起。UIRefreshControl 似乎并没有立即进行这种自定义。

我的 UIRefreshControl 初始化代码:

UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventValueChanged];
[self.tableView addSubview:refreshControl];

我的刷新:代码相当基本:

-(void)refresh:(id)sender {
(... refresh code ...)
[sender endRefreshing];
}

如何延迟刷新:功能,直到用户将手指从拉动中移开?

4

3 回答 3

39

我也遇到了同样的问题。我认为我的方法不是很好,但似乎可行。

  1. 在里面UIRefreshControl

    UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
    self.refreshControl = refreshControl;
    
  2. 检查UIRefreshControl用户完成拖动表格时的状态(UITableViewDelegate符合UIScrollViewDelegate

    - (void)scrollViewDidEndDecelerating:(UIScrollView*)scrollView
    {    
        if( self.refreshControl.isRefreshing )
            [self refresh];
    }
    
  3. 更新表

    - (void)refresh
    {
        [self.refreshControl endRefreshing];
    
        // TODO: Update here your items
    
        [self.tableView reloadData];
    }
    

希望它会帮助你。

于 2013-03-23T20:58:22.947 回答
20

UIRefreshControl已经有了在“正确”时间开始的住宿。下拉刷新控件的正确行为是在用户超过某个“足够远”的阈值后开始刷新,而不是在用户释放拖动时开始刷新。

为了实现这一点,您需要修改-refresh:方法以检查控件何时转换为refreshing状态:

-(void)refresh:(id)sender {
    UIRefreshControl *refreshControl = (UIRefreshControl *)sender;
    if(refreshControl.refreshing) {
        (... refresh code ...)
    }
}

请注意,您调用的任何方法都(... refresh code ...)应该是异步的,这样您的 UI 就不会冻结。您应该更改到主队列并-endRefreshing在您的(... refresh code ...)块结束时调用,而不是在结束时调用-refresh:

- (void)refresh:(id)sender {
    __weak UIRefreshControl *refreshControl = (UIRefreshControl *)sender;
    if(refreshControl.refreshing) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            /* (... refresh code ...) */
            dispatch_sync(dispatch_get_main_queue(), ^{
                [refreshControl endRefreshing];
                //reload the table here, too
            });
        });
    }
}

将控件事件更改为UIControlEventTouchUpInside将不起作用,因为UIRefreshControl它不是旨在直接与之交互的 UI 组件。用户永远不会触摸UIRefreshControl因此不会UIControlEventTouchUpInside触发任何事件。

于 2013-03-23T22:10:31.680 回答
3

可以使用 来安排刷新仅在手指抬起时发生NSRunLoop。在数组中调用-(void)performInModes:(NSArray<NSRunLoopMode> *)modes block:(void (^)(void))block;with 。NSRunLoopDefaultMode

当触摸仍然保持时,runloop 模式是UITrackingRunLoopMode,它只会在liftoff 后恢复到默认值。

于 2018-10-12T11:12:38.107 回答