How to use Timer when app is in background

I'm developing Push Notification for our chat app.

To enable Push Notification, our app will register the device token as well as some other information to another independent service, let's say "RegistrationService". Then any message going through the "RegistrationService" will know which device it should be sent to.

Now my issue is - Since every registration record in "RegistrationService" has a TTL of 24 hour, our app will need to do another registration once the expiration time is reached.

Currently I use the below codes in AppDelegate to start push notification and do the first time registration. I'm thinking if it is possible to resolve the above mentioned issue by embedding a "Timer". If so, can the timer work well when app is running in background?

As we know, Push Notification offers a solution for client to receive the message when app in background. If the timer/registration auto-renew doesn't work in background, it can be a big issue. (From this post, https://developer.apple.com/forums/thread/127444, looks like the timer can't work when app is in background. If so, do you have any other recommended ways to achieve this?)

    func application(

    _ application: UIApplication,

    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
    ) {

        let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }

        let token = tokenParts.joined()

        print("Device Token: \(token)")

        UserDefaults.standard.set(token, forKey: "APNSToken")

        // Start push notifications

        guard let apnsToken = UserDefaults.standard.string(forKey: "APNSToken") else {

            print("Failed to get APNS token")

            return

        }

        let semaphore = DispatchSemaphore(value: 0)

        DispatchQueue.global(qos: .background).async { [weak self] in

            guard let self = self else { return }

            guard let chatClient = self.chatClient else { return }

            chatClient.startPushNotifications(deviceToken: apnsToken) { result in

                switch result {

                case .success:

                    print("Started Push Notifications")

                case let .failure(error):

                    print("Failed To Start Push Notifications: \(error)")

                }

                semaphore.signal()

            }

            semaphore.wait()

        }

    }

As you know, Timer does not work in the background.

One common workaround is:

Detect when the app is going into the background

  • Convert each live timer into a local notification (at the timer's activation time)
  • Cancel the timer

On foregrounding the app:

  • Convert any outstanding local notifications back into Timers
  • Cancel the local notification

Of course, if the local notification fires while the app is backgrounded, it will require user intervention, before it can carry out any functionality.

Also of course, this workaround may not be suitable for your purpose (but perhaps the principle is helpful)?

How to use Timer when app is in background
 
 
Q