How to kill NSTimer after entering the background and create a new timer after the application returns to active?

So, I am creating a simple iOS application using Swift. I need to kill my NSTimer after the application starts the background and creates a new one after the application is active again.

My original solution was to create an NSTimer class NSTimer in ViewDidLoad() in the main controller file. And that causes an error in my application.

I think I need to kill the timer using applicationDidEnterBackground() in AppDelegate.swift . But I'm not quite sure how to do this. Should I create a timer class in AppDelegate.swift or in the main controller? I do not know how Swift files share classes.

I searched the Internet for solutions, but these posts are too old, the solutions are written in Objective-C.

I am absolutely new. Therefore, I hope that someone can explain this in Swift.

Here is the code in my main TodoTableViewController.swift controller:

 import UIKit import CoreData class TodoTableViewController: UITableViewController, NSFetchedResultsControllerDelegate {.... ... ... override func viewDidLoad() { super.viewDidLoad() var fetchRequest = NSFetchRequest(entityName: "Todo") let sortDescriptor = NSSortDescriptor(key: "dayleft", ascending: true) fetchRequest.sortDescriptors = [sortDescriptor] if let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext { fetchResultController = NSFetchedResultsController(fetchRequest:fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: nil) fetchResultController.delegate = self var e: NSError? var result = fetchResultController.performFetch(&e) todos = fetchResultController.fetchedObjects as [Todo] if result != true { println(e?.localizedDescription) } } var timer = NSTimer.scheduledTimerWithTimeInterval(10, target: self, selector:"update", userInfo:nil, repeats: true) } ... } 

If I am going to invalidate the timer in AppDelegate.swift , how can I refer to the timer that I created in TodoTableViewController.swift ? Or maybe I should put all the timer related code in AppDelegate.swift ?


Update

I tried using NSNotificationCenter, here is my code.

 import UIKit import CoreData class TodoTableViewController: UITableViewController, NSFetchedResultsControllerDelegate { ... var timer = NSTimer.scheduledTimerWithTimeInterval(10, target: self, selector:"viewDidLoad", userInfo:nil, repeats: true) func update(){ ..... } override func viewDidLoad() { super.viewDidLoad() ... let notificationCenter = NSNotificationCenter.defaultCenter() notificationCenter.addObserver(self, selector: "didEnterBackground", name: "UIApplicationDidEnterBackgroundNotification", object: UIApplication.sharedApplication()) notificationCenter.addObserver(self, selector: "didBecomeActive", name: "UIApplicationWillEnterForegroundNotification", object: UIApplication.sharedApplication()) } func didEnterBackground() { timer.invalidate() } func didBecomeActive() { var timer = NSTimer.scheduledTimerWithTimeInterval(10, target: self, selector:"update", userInfo:nil, repeats: true) } ... } 

Since the timer is declared in didBecomeActive() , an error appears in didEnterBackground() : it does not have a member named "timer". If I declare a timer outside didBecomeActive() , like the code above, the error message "Exam argument" in the call appears. I already parse the update() function in the selector. I do not know where this error came from.

+6
source share
2 answers

Updated your code and added some comments:

 class TodoTableViewController: UITableViewController, NSFetchedResultsControllerDelegate //better to instantiate timer inside viewDidLoad var timer: NSTimer! func update(){ } override func viewDidLoad() { super.viewDidLoad() startTimer() let notificationCenter = NSNotificationCenter.defaultCenter() //UIApplicationDidEnterBackgroundNotification & UIApplicationWillEnterForegroundNotification shouldn't be quoted notificationCenter.addObserver(self, selector: "didEnterBackground", name: UIApplicationDidEnterBackgroundNotification, object: nil) notificationCenter.addObserver(self, selector: "didBecomeActive", name: UIApplicationWillEnterForegroundNotification, object: nil) } func didEnterBackground() { self.timer.invalidate() } func didBecomeActive() { startTimer() } func startTimer() { self.timer = NSTimer.scheduledTimerWithTimeInterval(10, target: self, selector:"update", userInfo:nil, repeats: true) } } 

Also note that NSTimer strongly preserves its target . Therefore, when closing the viewcontroller-timer must be invalidated explicitly. Or a memory leak will occur and the TodoTableViewController will never be destroyed.

+10
source

Responsible for Objective-C, but I think it is very similar to Swift.

In ViewDidLoad, add two notifications:

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:[UIApplication sharedApplication]]; 

and

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didBecomeActive) name:UIApplicationWillEnterForegroundNotification object:[UIApplication sharedApplication]]; 

Then add this to the view controller class.

 - (void)didEnterBackground{ [_timer invalidate]; } - (void)didBecomeActive{ _timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(update) userInfo:nil repeats:YES]; } 
+1
source

Source: https://habr.com/ru/post/979533/


All Articles