ios - BGAppRefreshTask后台任务未执行

标签 ios swift background task

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

我已经设置了以下内容:

  • 启用了我的应用程序的“后台模式”功能,并检查了“背景提取”。
  • 在“允许的后台任务计划程序标识符”下的Info.plist中添加了我的背景ID:“com.XYZ.PearWeather.backgroundAlerts”。

  • 我已经从AppDelegate中的application(didFinishLaunchingWithOptions)注册了任务:
            BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.XYZ.PearWeather.backgroundAlerts", using: nil) { task in
                self.backgroundAlerts(task: task as! BGAppRefreshTask)
            }
    

    我正在AppDelegate内的func中安排任务,并从我的SceneDelegate sceneDidEnterBackground()调用它。它最初是一个静态函数,但是现在我将其更改为实例函数,并获得了AppDelegate实例(因为我在绝望中尝试了许多更改):
        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方案中,submit调用中没有错误。我为上面的timeIntervalSinceNow参数尝试了许多不同的值。我还从任务处理程序本身中调用此scheduleBackgroundAlerts()函数,如下所示:
        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()现在也非常简单:
        static func showNotification() {
    
            let now = Date()
            let bg = Locale.currentLocale().formattedTime(date: now)
            SettingsManager.shared.settings.bg = bg
        }
    

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

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

    就像我说的那样,使用以下命令从调试器中调用任务处理程序可以正常工作:
    e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"com.XYZ.PearWeather.backgroundAlerts"]
    

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

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

    最佳答案

    这是我用的。

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

    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)")
    }
    }
    

    关于ios - BGAppRefreshTask后台任务未执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61138351/

    相关文章:

    ios - 如何在实例方法中调用类型方法

    ios - 使用自动布局自动调整 UIPopoverController 的大小

    ios - 如何在iOS cocos2d中无限移动背景图片

    css - 如何更改 Sencha Touch 2 中的默认背景

    xcode - 如何添加背景图片

    横向模式下额外填充顶部的 iOS 导航项目问题

    iphone - 在 XCode 中创建应用的 LITE 版本

    IOS UITableViewRowAction : swipe on cell works randomly

    ios - 没有 Storyboard的 CollectionView Controller 创建

    ios - 如何在 iOS 文件系统中存储来自 UnsafeMutablePointer 的数据