简体   繁体   English

如何判断我的 iOS 13 后台任务是否已运行?

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

I'm trying out iOS Background Task for the first time.我第一次尝试 iOS 后台任务。 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.按照示例 WWDC'19 代码,我设置了一个简单的应用程序,在ViewController.viewDidLoad() UserDefaults键的值设置为 1,并在后台任务中将其设置为 2。 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.该值始终显示为 1,即使在让应用程序在后台运行一夜之后也是如此。 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?或者可能是我的UserDefaults值在前台和后台任务之间不同步,如几个 stackoverflow 问题中所讨论的那样? 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 .我已经检查了“签名和功能”下“后台模式”中的“后台获取”项目,并且我还在我的Info.plist I'm running the app on device, tethered to Xcode.我在设备上运行该应用程序,连接到 Xcode。

iOS 13.5.1, Xcode 11.5 iOS 13.5.1,Xcode 11.5

AppDelegate.swift : 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 : SceneDelegate.swift
Followingthis tutorial , I call scheduleAppRefresh() in SceneDelegate instead of AppDelegate and have modified these two functions:按照本教程,我在SceneDelegate而不是AppDelegate中调用scheduleAppRefresh()并修改了这两个函数:

    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 :最后,在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:这是我在 Xcode 控制台上打印出来的:

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 ?为什么UserDefaults.shared.integer(forKey: "bgtask")不增加第二个didBecomeActive

after I watch wwdc2019看完wwdc2019之后

https://developer.apple.com/videos/play/wwdc2019/707/ 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 https://forums.developer.apple.com/thread/124320

Well, I got background processing to work.好吧,我让后台处理工作。 Xcode console output: Xcode 控制台 output:

viewDidLoad:  1
didBecomeActive:  1
didEnterBackground:  1
didBecomeActive:  1
didEnterBackground:  1
                           // after about 15 minutes
didBecomeActive:  2
didEnterBackground:  2
                           // after staying in background overnight (~8 hours)
didBecomeActive:  19
didEnterBackground:  19

Instead of "Background fetch," I ticked "Background processing" in "Background Modes" under "Signing & Capabilities".我在“签名和功能”下的“后台模式”中勾选了“后台处理”,而不是“后台获取”。

AppDelegate.swift: 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! BGProcessingTask)
        }
        return true
    }

    func scheduleAppRefresh() {

        let request = BGProcessingTaskRequest(identifier: "com.example.BGTask.refresh")
        request.requiresNetworkConnectivity = false
        request.requiresExternalPower = false

        do {
            try BGTaskScheduler.shared.submit(request)
        } catch {
            print("Could not schedule app refresh: \(error)")
        }
    }

    func handleAppRefresh(task: BGProcessingTask) {
        scheduleAppRefresh()
        
        task.expirationHandler = {
            task.setTaskCompleted(success: false)
        }
        
        // increment instead of a fixed number
        UserDefaults.standard.set(UserDefaults.standard.integer(forKey: "bgtask")+1, forKey: "bgtask")

        task.setTaskCompleted(success: true)
    }
    
    // MARK: UISceneSession Lifecycle
    // rest of templated AppDelegate.swift

And no other changes to the other files.并且没有对其他文件进行其他更改。

Now why does BGProcessing work while BGAppRefresh doesn't?现在为什么 BGProcessing 工作而 BGAppRefresh 不工作?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM