Search code examples
iosuitableviewgestureuipangesturerecognizeruirefreshcontrol

iOS - stop UIRefreshControl on push up


I've recently implemented UIRefreshControl to load data from iCloud when pulled down, however, I find it intuitive for user to push the UITableView back up when he demands to stop refreshing. I am not able to figure out how to detect this without using UIPanGestureRecognizer which would then remove the functionality of my UITableView.

Is there any way I can detect pushing the UITableView back up during refresh, without removing functionality of existing tableview? Thank you.


Solution

  • What I'd do in this situation is to take advantage of the fact that a UITableViewDelegate conforms to the UIScrollViewDelegate. That way you can figure out when different scrolling events occur on your tableView. If you are a subclass of a UITableViewController, you already conform to the UITableViewDelegate, so you're all good there.

    The first thing I did was to have a property for the contentOffset so that I can record it when the dragging is starting.

    @property (nonatomic, strong) NSNumber *contentOffsetAtStartOfDragging;
    

    The reason I chose to make this a NSNumber instead of say a CGFloat which may seem more natural, is because I don't want that property stuck with some value when it's not needed. When that property is no longer useful to me, I want it to be nil. That's just my design choice though, it wouldn't really make any difference.

    Anyway, the way I did this was to record that contentOffset when the dragging is starting, and then comparing that to the contentOffset when the dragging ended. That was I know if the user has been scrolling to a contentOffset that is lower than what it was at the start of the dragging, and I can end the refreshing.

    Also when the dragging is done, I set my property to nil for the reason explained above.

    - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
    {
        if ([self.refreshControl isRefreshing]) {
            self.contentOffsetAtStartOfDragging = [NSNumber numberWithFloat:scrollView.contentOffset.y];
        }
    }
    
    - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
    {
        if ([self.refreshControl isRefreshing] &&
            scrollView.contentOffset.y > [self.contentOffsetAtStartOfDragging floatValue])
        {
            [self.refreshControl endRefreshing];
        }
    
        self.contentOffsetAtStartOfDragging = nil;
    }
    

    Hope this was helpful. Let me know if it worked out for you.