2

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.

Lance Samaria
  • 17,576
  • 18
  • 108
  • 256
  • this `refreshControl.endRefreshing()` should be on completion handler of the request. – Mojtaba Hosseini Sep 07 '19 at 07:11
  • it does get called in the completion handler of the request. It happens in the a firebase callback and I call it on the mainQueue. I didn't add the code because I didn't think it was relevant to the question. Thanks though – Lance Samaria Sep 07 '19 at 07:13

2 Answers2

1

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()
    }
}
Lance Samaria
  • 17,576
  • 18
  • 108
  • 256
0

This work needs to be handled on the main thread. This will handle the stopping of the spinner's animation for you and then the user can pull to refresh once again.

@objc private func handleRefreshControl() {
        // Reload Data
        DispatchQueue.main.async {
            self.collectionView.refreshControl?.endRefreshing()
        }
    }
  • Remember that Stack Overflow isn't just intended to solve the immediate problem, but also to help future readers find solutions to similar problems, which requires understanding the underlying code. This is especially important for members of our community who are beginners, and not familiar with the syntax. Given that, **can you [edit] your answer to include an explanation of what you're doing** and why you believe it is the best approach? – Jeremy Caney Oct 26 '22 at 00:04