Swift 3 - How to make timer work in background

56,867

Solution 1

you can go to Capabilities and turn on background mode and active Audio. AirPlay, and picture and picture.

It really works . you don't need to set DispatchQueue . you can use of Timer.

Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { (t) in

   print("time")
}

Solution 2

A timer can run in the background only if both the following are true:

  • Your app for some other reason runs in the background. (Most apps don't; most apps are suspended when they go into the background.) And:

  • The timer was running already when the app went into the background.

Solution 3

This works. It uses while loop inside async task, as suggested in another answer, but it is also enclosed within a background task

func executeAfterDelay(delay: TimeInterval, completion: @escaping(()->Void)){
    backgroundTaskId = UIApplication.shared.beginBackgroundTask(
        withName: "BackgroundSound",
        expirationHandler: {[weak self] in
            if let taskId = self?.backgroundTaskId{
                UIApplication.shared.endBackgroundTask(taskId)
            }
        })
    
    let startTime = Date()
    DispatchQueue.global(qos: .background).async {
        while Date().timeIntervalSince(startTime) < delay{
            Thread.sleep(forTimeInterval: 0.01)
        }
        DispatchQueue.main.async {[weak self] in
            completion()
            if let taskId = self?.backgroundTaskId{
                UIApplication.shared.endBackgroundTask(taskId)
            }
        }
    }
}

Solution 4

Timer won't work in background. For background task you can check this link below...

https://www.raywenderlich.com/143128/background-modes-tutorial-getting-started

Solution 5

============== For Objective c ================

create Global uibackground task identifier.

UIBackgroundTaskIdentifier bgRideTimerTask;

now create your timer and add BGTaskIdentifier With it, Dont forget to remove old BGTaskIdentifier while creating new Timer Object.

 [timerForRideTime invalidate];
 timerForRideTime = nil;

 bgRideTimerTask = UIBackgroundTaskInvalid;

 UIApplication *sharedApp = [UIApplication sharedApplication];       
 bgRideTimerTask = [sharedApp beginBackgroundTaskWithExpirationHandler:^{

                            }];
 timerForRideTime =  [NSTimer scheduledTimerWithTimeInterval:1.0
                                                                                 target:self
                                                                               selector:@selector(timerTicked:)
                                                                               userInfo:nil
                                                                                repeats:YES]; 
                                                   [[NSRunLoop currentRunLoop]addTimer:timerForRideTime forMode: UITrackingRunLoopMode];

Here this will work for me even when app goes in background.ask me if you found new problems.

Share:
56,867
Admin
Author by

Admin

Updated on September 17, 2020

Comments

  • Admin
    Admin over 3 years

    i am trying to do an application which can make a timer run in background.

    here's my code:

    let taskManager = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(self.scheduleNotification), userInfo: nil, repeats: true)
            RunLoop.main.add(taskManager, forMode: RunLoopMode.commonModes)
    

    above code will perform a function that will invoke a local notification. this works when the app is in foreground, how can i make it work in the background?

    i tried to put several print lines and i saw that when i minimize (pressed the home button) the app, the timer stops, when i go back to the app, it resumes.

    i wanted the timer to still run in the background. is there a way to do it?

    here's what i want to happen:

    run app -> wait 10 secs -> notification received -> wait 10 secs -> notification received -> and back to wait and received again

    that happens when in foreground. but not in background. pls help.