iosswiftuicollectionviewuirefreshcontrol

How to check if the refresh control is or isn't refreshing inside its target action method


I have a collectionView with a refreshControl

lazy var refreshControl: UIRefreshControl = {
    let refreshControl = UIRefreshControl()
    refreshControl.addTarget(self,
                             action: #selector(handleRefreshControl(_:)),
                             for: .valueChanged)
    return refreshControl
}()

//create collectionView
collectionView.refreshControl = refreshControl

I press a button to get some data from the server. Once the process starts I use refreshControl.refreshManually() to start refreshing.

getDataBarButton() {

    refreshControl.refreshManually()

    fetchData()
}

Once the data is retrieved I call refreshControl.endRefreshing() to stop the refresh.

func fetchData() {

    // got the data

    refreshControl.endRefreshing()
}

All of that works fine. This isn't a situation where if it's pulled more data is pulled from the db because only the button does that. Once I pull the cv I want to show the refreshControl and then remove it. I don't want to completely get rid of the refreshControl after it's done because the button might get pressed again.

The problem is once I pull the cv, the refreshControl starts refreshing and doesn't stop. It just stays there.

I check to see if it stopped but this doesn't work:

@objc fileprivate func handleRefreshControl(_ sender: UIRefreshControl) {
    if refreshControl.isRefreshing {
        print("refreshing is occurring")
        return
    }
    refreshControl.refreshManually()
    refreshControl.endRefreshing()
}

The way I see it, after the data is returned and after refreshControl.endRefreshing() is called, once I pull the cv the print statement inside if refreshControl.isRefreshing shouldn't run but it does.

Outside of creating and toggling variables like var isRefreshing = false/true how can check to see the refreshControl is or isn't refreshing inside its target action?

Just for context, if you’re reading this question on the stack overflow iOS app, just pull down and watch what happens. There is nothing to refresh but when the pull takes place a refresh control is shown then gets removed. I want to do the same exact thing.


Solution

  • I couldn't find any other way to do it but to use a property

    var isRefreshing = false // 1. initially set to false
    
    func startRefreshing() {
    
        isRefreshing = true // 2. create a function that sets isRefreshing to true and also calls .refreshManually
        refreshControl.refreshManually()
    }
    
    func endRefreshing() {
        isRefreshing = false  //  3. create a function that sets isRefreshing to false and also calls .endRefreshing
        refreshControl.endRefreshing()
    }
    
    getDataBarButton() {
    
        startRefreshing() // 4. when then button is pressed call the function to start refreshing
        fetchData()
    }
    
    func fetchData() {
    
        // got the data
        endRefreshing()  // 5. after the data is returned call the function to endRefreshing
    }
    
    func handleRefreshControl(_ sender: UIRefreshControl) {
    
        // 6. in the refresher's target action check to see if isRefreshing == false and if it is then call refreshControl.endRefreshing()
        if !isRefreshing {
    
            refreshControl.endRefreshing()
        }
    }