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.
Init
UIRefreshControl
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];self.refreshControl = refreshControl;
Check state of
UIRefreshControl
when user finish dragging the table (UITableViewDelegate
conforms toUIScrollViewDelegate
)- (void)scrollViewDidEndDecelerating:(UIScrollView*)scrollView{ if( self.refreshControl.isRefreshing ) [self refresh];}
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.