FaiChou
FaiChou

Reputation: 837

Run timer in background

In iOS system app clock, when I start a timer or stopwatch, quit the app, kill, and reopen it, the timer or stopwatch is still running.

How can I have a timer running in the background?
And how did Apple do it?

Upvotes: 4

Views: 10419

Answers (3)

Vimal Christina
Vimal Christina

Reputation: 1

add this code to in appdelagate.swift

var backgroundUpdateTask: UIBackgroundTaskIdentifier = 0

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    return true
}

func applicationWillResignActive(application: UIApplication) {
    self.backgroundUpdateTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({
        self.endBackgroundUpdateTask()
    })
}

func endBackgroundUpdateTask() {
    UIApplication.sharedApplication().endBackgroundTask(self.backgroundUpdateTask)
    self.backgroundUpdateTask = UIBackgroundTaskInvalid
}

func applicationWillEnterForeground(application: UIApplication) {
    self.endBackgroundUpdateTask()
}

Upvotes: -1

Gabs
Gabs

Reputation: 422

It's possible through a token that identifies a request to run in the background.
Like this: var bgTask = UIBackgroundTaskIdentifier()

Here is how to use it:

var bgTask = UIBackgroundTaskIdentifier()
    bgTask = UIApplication.shared.beginBackgroundTask(expirationHandler: {
        UIApplication.shared.endBackgroundTask(bgTask)
    })
    let timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(notificationReceived), userInfo: nil, repeats: true)
    RunLoop.current.add(timer, forMode: RunLoopMode.defaultRunLoopMode)

I hope it would be useful!

Upvotes: 14

Vollan
Vollan

Reputation: 1915

Store the current timer and clock value inside a long attribute in seconds or milliseconds inside UserDefault when you close the app. I use a generic one i can share:

static let userDefaults = UserDefaults.standard

    public static func set<T: Hashable> (withValue value: T, andKey key: String) {
        userDefaults.set(value, forKey: key)
        userDefaults.synchronize()
    }
    public static func get(forKey key: String) -> Any? {
        if((userDefaults.object(forKey: key)) != nil){
            let data = userDefaults.object(forKey: key) as? Any
            return data
        }
        return nil
    }

When you start the application again, use the "get" method to get; lets say seconds and stored time. Then you can compare the current time to the stored one and calculate the seconds in between and add the time difference to the stored seconds and you can just set the timer to the presented value and keep it going.

Here is how you set it when you close the application:

NotificationCenter.default.addObserver(self, selector: #selector(storeTime), name: NSNotification.Name.UIApplicationWillResignActive, object: nil)

func storeTime() {
     "UserDefaultClassName".set(withValue: "preferably dictionary", andKey: String)
}

Upvotes: 1

Related Questions