4

I am trying to show a refresh control right when the view loads to show that I am getting getting data from Parse. The refresh control works as it should when the app is running, but I cannot get it to fire programmatically from anywhere in my app. This is the code that does not appear to run:

 override func viewDidAppear(animated: Bool) {
    self.refresher.beginRefreshing()
 }

Not only does this not run, but having the code in the app changes the attributes of the refresh control. When I have this code in the app, and show the refresher from user interaction, the refresh control does not have its attributed title as it usually does nor does it run the code that it should.

Christian Ayscue
  • 641
  • 1
  • 7
  • 22
  • Check this question/answer [UIRefreshControl not working when called prorgammatically](http://stackoverflow.com/questions/14718850/uirefreshcontrol-beginrefreshing-not-working-when-uitableviewcontroller-is-ins) – Bardh Lohaj Feb 16 '15 at 20:51

2 Answers2

5

I needed to add a delay between setContentOffset and the self.refreshControl?.sendActions(for: .valueChanged) call. Without the delay, the refreshControl's attributedTitle would not render.

This works in iOS 10 (Swift 3):

self.tableView.setContentOffset(CGPoint(x:0, y:self.tableView.contentOffset.y - (self.refreshControl!.frame.size.height)), animated: true)

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2, execute: {
  self.refreshControl?.sendActions(for: .valueChanged)
})
dcrow
  • 570
  • 5
  • 11
  • I tried your solution but it doesn't gets animated. – Zac Oct 23 '16 at 09:40
  • The first `self.tableView.setContentOffset(CGPoint(x:0, y:self.tableView.contentOffset.y - (self.refreshControl!.frame.size.height)), animated: true)` + `self.refreshControl?.beginRefreshing()` works for me on iOS 10. Didn't need the sendActions call. – nmdias Jul 12 '17 at 10:09
  • Thanks. Without the delay the title doesn't show up! – hendra Dec 01 '17 at 11:42
  • I'm surprised no-one brought it up: I'd suggest to call required method directly instead of using target-action via `sendActions(for:)` method. It looks like a workaround for me - why would one wanted to wait 0.2 seconds (or any amount of time) if it's possible to do all necessary work right away? – derpoliuk Mar 30 '18 at 21:31
5

Here's an extension working on 10.3:

extension UIRefreshControl {
    func refreshManually() {
        if let scrollView = superview as? UIScrollView {
            scrollView.setContentOffset(CGPoint(x: 0, y: scrollView.contentOffset.y - frame.height), animated: false)
        }
        beginRefreshing()
        sendActions(for: .valueChanged)
    }
}
henrique
  • 1,072
  • 10
  • 17
  • 2
    The sendAction(for:) caused a recursive call which created unexpected behavior making the method call itself recursively. Other than that the extension works great. – Austin Betzer Aug 05 '20 at 16:22