UITableView dragging distance with UIRefreshControl

纵然是瞬间 提交于 2019-12-05 04:40:37
kbtzr

I had a similar problem and it's quite possible that's the same cause for you. For me happens that I hided the scroll indicator making me unable to see the obvious cause of the problem: the UIScrollView's height is much greater than its superView...

Double check your UIScrollView's height because the "dragging distance" it's just a percentage of that height. Same goes for UITableView too, since it's a child class of UIScrollView.

EDIT: Seems that this isn't the only way to reproduce this problem, since the required drag distance to trigger the refresher is calculated in a buggy way. Refer to this question for more info.

But in general it will happen if your UIScrollView's height is different than his parent container (e.g the screen itself).

You probably need to not use UIRefreshControl and just utilize scrollViewDidScroll (or tableViewDidScroll if a tableView) on handle your refresh accordingly since UIRefreshControl can't be modified.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if ((scrollView.contentOffset.y + scrollView.frame.size.height) >=    scrollView.contentSize.height)
    {
        // Refresh from here
    }
}

After some extensive testing and playing around with UIKit I have come to a conclusion.

TL;DR

UIRefreshControl isn't smart enough. To fix add this code in viewDidAppear or viewDidLayoutSubviews

let refreshControl = scrollView.refreshControl
scrollView.refreshControl = nil
scrollView.refreshControl = refreshControl

Test setup

Single UIViewController in a Storyboard with a UIView as its view which in turn has a UIScrollView as only subview which in turn has a single UIView as subview with top,right,bottom,left,width,height constraints equal to superview. The viewController has freeform size with 1200p height.

In the subclass of the UIViewController a UIRefreshControl is added by setting the UIScrollView#refreshControl to a new UIRefreshControl inside viewDidLoad.

When running the application in an iPhone X simulator and dragging the scrollView to perform a "Pull to refresh" one must drag considerably longer to make the refreshControl animating and send its notification it was pulled down.

The problem

One of my hypotheses was that the UIRefreshControl gets its dragging distance set once it is added to the scrollView and since AutoLayout hasen't updated the root view's subviews at viewDidLoad the scrollView has a height of 1180.0p instead of the correct 768.0p thus the refreshControl's dragging distance would be calculated for the height 1180.0p instead of 768.0p and thus become much longer than expected when running the app.

The solution

By updating the scrollView's refreshControl after the correct size for the scrollView has been set the correct dragging distance is calculated.

This update has to occur in a function where the correct size of the scrollView has been calculated, for example viewDidAppear and viewDidLayoutSubviews.

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    let refreshControl = scrollView.refreshControl
    scrollView.refreshControl = nil
    scrollView.refreshControl = refreshControl
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!