Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tell if my iOS 13 background task has run?

Tags:

xcode

ios

swift

I'm trying out iOS Background Task for the first time. Following the sample WWDC'19 code, I set up a simple app that sets a UserDefaults key's value to 1 in the ViewController.viewDidLoad() and set it to 2 in the background task. I have the value printed before entering background and upon returning to foreground. The value consistently prints as 1, even after letting the app sit in the background overnight. Is my background task not run? Or could it be that my UserDefaults value is not synchronized between the foreground and background tasks, as discussed in several stackoverflow questions? Or am I doing something else wrong? Any pointer appreciated.

I have checked the "Background fetch" item in "Background Modes" under "Signing & Capabilities" and I have also added "com.example.BGTask.refresh" as "item 0" under "Permitted background task scheduler" in my Info.plist. I'm running the app on device, tethered to Xcode.

iOS 13.5.1, Xcode 11.5

AppDelegate.swift:

import UIKit
import BackgroundTasks

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.example.BGTask.refresh", using: nil) { task in
            self.handleAppRefresh(task: task as! BGAppRefreshTask)
        }
        return true
    }

    func scheduleAppRefresh() {
        let request = BGAppRefreshTaskRequest(identifier: "com.example.BGTask.refresh")
        request.earliestBeginDate = Date(timeIntervalSinceNow: 15*60)
        do {
            try BGTaskScheduler.shared.submit(request)
        } catch {
            print("Could not schedule app refresh: \(error)")
        }
    }

    func handleAppRefresh(task: BGAppRefreshTask) {
        scheduleAppRefresh()

        task.expirationHandler = {
            task.setTaskCompleted(success: false)
        }

        UserDefaults.standard.set(2, forKey: "bgtask")
        task.setTaskCompleted(success: true)
    }


    // MARK: UISceneSession Lifecycle
    // rest of templated AppDelegate.swift

SceneDelegate.swift:
Following this tutorial, I call scheduleAppRefresh() in SceneDelegate instead of AppDelegate and have modified these two functions:

    func sceneDidBecomeActive(_ scene: UIScene) {
        print("didBecomeActive: ", UserDefaults.standard.integer(forKey: "bgtask"))
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
        print("didEnterBackground: ", UserDefaults.standard.integer(forKey: "bgtask"))
        (UIApplication.shared.delegate as! AppDelegate).scheduleAppRefresh()
    }

Finally, in ViewController.swift:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        UserDefaults.standard.set(1, forKey: "bgtask")
        print("viewDidLoad: ", UserDefaults.standard.integer(forKey: "bgtask"))
    }
}

This is what I get printed out on the Xcode console:

viewDidLoad:  1
didBecomeActive:  1
                        // tap the Home button
didEnterBackground:  1
                        // after a suitably long time, tap the app icon
didBecomeActive:  1

Why doesn't UserDefaults.shared.integer(forKey: "bgtask") get incremented by the second didBecomeActive?

like image 905
Andy Hill Avatar asked Nov 06 '22 07:11

Andy Hill


1 Answers

after I watch wwdc2019

https://developer.apple.com/videos/play/wwdc2019/707/

The task will be executed only when the system decides to do so

You can check to this forum discussion link too :

https://forums.developer.apple.com/thread/124320

like image 117
Wahyudimas Avatar answered Nov 15 '22 06:11

Wahyudimas