0

I have a UITableView that has a refreshControl added as

func addRefreshControl() {
    refreshControl.addTarget(self, action: #selector(refresh), for: .valueChanged)
    testTableView.addSubview(refreshControl)
}

When i scroll the tableView down the refreshControl begins animating. But when i press the home button and when app goes in suspended state, the refresh control stops.

To resume animation i did as follow:

     func applicationDidBecomeActive(_ application: UIApplication) {
    let vc = window?.rootViewController as! ViewController
    if vc.refreshControl.isRefreshing {
        vc.refreshControl.endRefreshing()
        vc.refreshControl.beginRefreshing()
        vc.testTableView.setContentOffset(CGPoint(x:0,y:vc.testTableView.contentOffset.y - vc.refreshControl.frame.size.height) , animated: true)
    }
}

But the refresh control doesnot start. Here is the sample project, i have attached for quick reference.

What should i do to start animation when the app wakes from suspended state?

Costello
  • 105
  • 6

2 Answers2

0

In AppDelegate you have by standard:

func applicationDidEnterBackground(_ application: UIApplication) {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

Attention on comments.

Then you have the method:

func applicationWillEnterForeground(_ application: UIApplication) {
    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}

So first method is called when you press home button, change from one app to another through multitasking or press on/off button to lock the fone.

The second one is called during transition from background state to foreground.

The one that you may want to use is:

func applicationDidBecomeActive(_ application: UIApplication) {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

Where happens right after the transition state and the app is in foreground mode.

Once it is done, you have another issue in your code, you're instantiating a new instance of your view controller:

let vc = window?.rootViewController as! ViewController
if vc.refreshControl.isRefreshing {
    vc.refreshControl.endRefreshing()
    vc.refreshControl.beginRefreshing()
    vc.testTableView.setContentOffset(CGPoint(x:0,y:vc.testTableView.contentOffset.y - vc.refreshControl.frame.size.height) , animated: true)
}

This means you have a new instance of your refreshControl thus this is not yet refreshing. Where lead your code to never work.

Below you can find the complete code to make it work following your implementation. Keep in mind that there are different approaches to make it without Notifications. You can use for example viewWillAppear method. But i'm using delegate as your code states on it.

Your view controller:

//
//  ViewController.swift
//  TestProject
//
//  Created by Anish on 4/2/18.
//  Copyright © 2018 Costello. All rights reserved.
//

import UIKit

var refreshControl = UIRefreshControl()

class ViewController: UIViewController {

    @IBOutlet weak var testTableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        testTableView.dataSource = self
        NotificationCenter.default.addObserver(self, selector: #selector(ViewController.resumeRefreshing), name: NSNotification.Name(rawValue: "resumeRefreshing"), object: nil)
        addRefreshControl()
    }


    @objc func addRefreshControl() {
        refreshControl.addTarget(self, action: #selector(refresh), for: .valueChanged)
        refreshControl.tag = 1
        testTableView.addSubview(refreshControl)
    }

    @objc func resumeRefreshing() {
        refreshControl.endRefreshing()
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            refreshControl.beginRefreshing()
            self.testTableView.setContentOffset(CGPoint(x:0,y:-60) , animated: true)
        }
    }

    @objc func refresh() {
        print("isRefreshing")
    }

}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 20
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = "Hello"
        return cell
    }

}

And your delegate:

//
//  AppDelegate.swift
//  TestProject
//
//  Created by Costello on 4/2/18.
//  Copyright © 2018 Costello. All rights reserved.
//

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        if refreshControl.isRefreshing {
            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "resumeRefreshing"), object: nil)
            //
        }
    }
}
GIJOW
  • 2,307
  • 1
  • 17
  • 37
0

Below code worked for me:

    func applicationDidBecomeActive(_ application: UIApplication) {
    let vc = self.window?.rootViewController as! ViewController
    vc.testTableView.setContentOffset(.zero , animated: true)
    if vc.refreshControl.isRefreshing {
        vc.refreshControl.endRefreshing()
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
            vc.testTableView.setContentOffset(CGPoint(x: 0, y: -vc.refreshControl.frame.size.height), animated: true)
            vc.refreshControl.beginRefreshing()
        }
    }
}
Costello
  • 105
  • 6