本文介绍了BGAppRefreshTask后台任务未执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用新的iOS13后台任务框架,并实现了BGAppRefreshTask类型.我的问题是,即使等待了几个小时,我的设备也永远不会调用任务,但是我能够使用调用_simulateLaunchForTaskWithIdentifier的调试器技巧成功运行代码.

I am using the new iOS13 background task framework, with the implementation of a BGAppRefreshTask type. My problem is, my device is never calling the task, even after waiting several hours, but I am able to successfully run the code using the Debugger trick of calling _simulateLaunchForTaskWithIdentifier.

我已经设置了以下内容:

I have setup the following:

  • 为我的应用启用了后台模式"功能,并选中背景提取".
  • 将我的背景ID添加到允许的后台任务调度程序标识符"下的Info.plist:"com.XYZ.PearWeather.backgroundAlerts".

我已经从AppDelegate中的application(didFinishLaunchingWithOptions)注册了任务:

I have registered the task from application(didFinishLaunchingWithOptions) in my AppDelegate:

        BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.XYZ.PearWeather.backgroundAlerts", using: nil) { task in
            self.backgroundAlerts(task: task as! BGAppRefreshTask)
        }

我正在AppDelegate内的func中安排任务,并从我的SceneDelegate sceneDidEnterBackground()调用它.它最初是一个静态函数,但是现在我将其更改为实例函数,并获得了AppDelegate实例(因为我在绝望中尝试了许多更改):

I am scheduling the task in a func within the AppDelegate, and calling it from my SceneDelegate sceneDidEnterBackground(). It was originally a static func, but I have now changed it to an instance func, and getting the AppDelegate instance (since I have tried many changes in desperation):

    func sceneDidEnterBackground(_ scene: UIScene) {
        (UIApplication.shared.delegate as! AppDelegate).scheduleBackgroundAlerts()
    }
    func scheduleBackgroundAlerts() {
        let request = BGAppRefreshTaskRequest(identifier: "com.XYZ.PearWeather.backgroundAlerts")

        request.earliestBeginDate = Date(timeIntervalSinceNow: 5 * 60)

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

至少在Debugger方案中,提交调用中没有错误.我为上面的timeIntervalSinceNow参数尝试了许多不同的值.我还从任务处理程序本身中调用此scheduleBackgroundAlerts()函数,如下所示:

At least in the Debugger scenario, there is no error in the submit call. I have tried many different values for the timeIntervalSinceNow parameter above. I am also calling this scheduleBackgroundAlerts() func from the task handler itself, which is as follows:

    func backgroundAlerts(task: BGAppRefreshTask) {

        scheduleBackgroundAlerts()

        task.expirationHandler = {
            // After all operations are cancelled, the completion block below is called to set the task to complete.
            task.setTaskCompleted(success: false)
        }

        AlertsOperation.showNotification()


        task.setTaskCompleted(success: true)
    }

此实现已发生了很大变化-我最初使用了OperationQueue,尝试将scheduleBackgroundAlerts()调用放在函数的开头和结尾,等等.现在将其剥离. AlertOperation.showNotification()现在也非常简单:

This implementation has changed a lot - I have originally used an OperationQueue, tried placing the scheduleBackgroundAlerts() call at the beginning and end of the func, etc. Now it is stripped down. The AlertOperation.showNotification() is also very simple now:

    static func showNotification() {

        let now = Date()
        let bg = Locale.currentLocale().formattedTime(date: now)
        SettingsManager.shared.settings.bg = bg
    }

这只是在UserDefaults中存储一个值(在我的SettingsManager中,其详细信息在这里不相关),我可以在我的应用中回读以查看是否发生了任何事情.

This is just storing a value in UserDefaults (in my SettingsManager, details of which are not relevant here) that I am able to read back in my app to see if anything happened.

现在,此函数的原始实现使用UNUserNotificationCenter等发出本地通知,这是我在此后台任务中要执行的操作.在Debugger上可以正常工作,但是我将其简化为简单的代码,只是实现了一个很小的实现.

Now, the original implementation of this func issues a local notification using UNUserNotificationCenter etc, which is what I am trying to do in this background task. This worked fine from the Debugger, but I reduced it to this simple code just to make a very small implementation.

正如我所说,使用以下命令从调试器中调用任务处理程序可以正常工作:

As I say, calling the task handler from the Debugger works fine, using:

e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.XYZ.PearWeather.backgroundAlerts"]

但是设备本身没有任何反应.我看不到我错过的一切.我也不知道如何从后台任务处理程序中记录任何异常.

But nothing is happening from the device itself. I cannot see what I have missed. I do not know how to log any exception from within the background task handler either.

我是Swift和iOS的新手,因此对任何指针都表示赞赏.上面的大多数代码几乎都是该主题的许多教程的副本.但是,对我而言,一切都无法正常进行,我的选择已经用光了!

I am new to Swift and iOS, so any pointers appreciated. Most of the code above is almost a copy of the many tutorials on this subject. For me, though, things are not working and I have run out of options!

推荐答案

这是我用的.

在我的AppDelegate中,为iOS13代码.不包括较旧的样式获取:

In my AppDelegate, the iOS13 code. Older style fetch not included:

class AppDelegate: UIResponder, UIApplicationDelegate, URLSessionDelegate, UNUserNotificationCenterDelegate {
var backgroundSessionCompletionHandler: (() -> Void)?
var backgroundSynchTask: UIBackgroundTaskIdentifier = .invalid

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13.0, *) {
    BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.WH.Air-Compare.WayneBGrefresh", using: nil) { task in
        self.handleAppRefresh(task: task as! BGAppRefreshTask)
        self.logSB.verbose("iOS 13  Registered for Background duty")
    }
} else {
    // Fallback on earlier versions
    self.logSB.verbose("iOS < 13  Registering for Background duty")
UIApplication.shared.setMinimumBackgroundFetchInterval(UIApplication.backgroundFetchIntervalMinimum)
}
}

func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler:@escaping () -> Void) {
let dateFormatter = DateFormatter()  // format the date for output
dateFormatter.dateStyle = DateFormatter.Style.medium
dateFormatter.timeStyle = DateFormatter.Style.long
let convertedDate = dateFormatter.string(from: Date())
self.logSB.info("Background URLSession handled at \(convertedDate)")
self.logSB.info("Background URLSession ID \(identifier)")
let config = URLSessionConfiguration.background(withIdentifier: "WayneBGconfig")
let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
session.getTasksWithCompletionHandler { (dataTasks, uploadTasks, downloadTasks) -> Void in
    // yay! you have your tasks!
    self.logSB.info("Background completion handler here with \(downloadTasks.count) tasks")
    for i in 0...max(0,downloadTasks.count - 1) {
        let description: String = downloadTasks[i].taskDescription!
        self.logSB.info("Task ID \(i) is \(description)")
    }
}
backgroundSessionCompletionHandler = completionHandler
}

func applicationDidEnterBackground(_ application: UIApplication) {
if #available(iOS 13.0, *) {
    scheduleAppRefresh()
} else {
    // Fallback on earlier versions
}
}

@available(iOS 13.0, *)
func scheduleAppRefresh() {
logSB.info("Scheduling the AppRefresh in iOS 13 !!")
let request = BGAppRefreshTaskRequest(identifier: "com.WH.Air-Compare.WayneBGrefresh")
request.earliestBeginDate = Date(timeIntervalSinceNow: 2 * 60) // Fetch no earlier than 2 minutes from now

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

这篇关于BGAppRefreshTask后台任务未执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 21:58