UIRefreshControl - How do I make the refresh action occur after the touch is released? UIRefreshControl - How do I make the refresh action occur after the touch is released? ios ios

UIRefreshControl - How do I make the refresh action occur after the touch is released?


I've also stuck with the same problem. I don't think that my approach is very nice, but seems like it works.

  1. Init UIRefreshControl

    UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];self.refreshControl = refreshControl;
  2. Check state of UIRefreshControl when user finish dragging the table (UITableViewDelegate conforms to UIScrollViewDelegate)

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

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

Hope it will help you.


UIRefreshControl already has accommodations for starting at the "right" time. The correct behavior for a pull-to-refresh control is to start the refresh after the user has crossed some "far enough" threshold, not when the user has released their drag.

In order to accomplish this, you need to modify your -refresh: method to check for when the control has transitioned into the refreshing state:

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

Note that any method you call for your (... refresh code ...) should be asynchronous, so that your UI doesn't freeze. You should change to main queue and call -endRefreshing at the end of your (... refresh code ...) block, instead of at the end of -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            });        });    }}

Changing the control event to UIControlEventTouchUpInside will not work because UIRefreshControl is not a UI component intended to be directly interacted with. The user will never touch the UIRefreshControl, so no UIControlEventTouchUpInside event can be triggered.


Scheduling the refresh to only occur when the finger has lifted can be achieved by using NSRunLoop. Call -(void)performInModes:(NSArray<NSRunLoopMode> *)modes block:(void (^)(void))block; with NSRunLoopDefaultMode in the array.

While the touch is still held, the runloop mode is UITrackingRunLoopMode, it will only go back to the default after liftoff.