后台任务 (.backgroundTask) 在 SwiftUI 中不起作用

问题描述 投票:0回答:2

我已在

plist.info
中使用标识符
updateCountry
配置后台任务,并将后台模式获取和处理作为功能。 我有具有以下功能的 locationManager:

func registerBackgroundTask() {
    BGTaskScheduler.shared.register(forTaskWithIdentifier: "updateCountry", using: nil) { task in
        self.handleAppRefresh(task: task as! BGAppRefreshTask)
        print("register backgoundtask")
    }
}

func handleAppRefresh(task: BGAppRefreshTask) {
    print("registrando pais")
    scheduleBackgroundTask()
    DispatchQueue.global().async {
        self.detectCountry()
        
        task.setTaskCompleted(success: true)
        print("Background task completed.")
    }
}

func scheduleBackgroundTask() {
    print("request updateCountry")
    let request = BGAppRefreshTaskRequest(identifier: "updateCountry")
    request.earliestBeginDate = Date(timeIntervalSinceNow: 60 * 1) // 1 minute
    
    do {
        try BGTaskScheduler.shared.submit(request)
        print("Background task scheduled successfully.")
    } catch {
        print("Unable to submit task: \(error)")
    }
}

我以这种方式调用这个函数,其中

handleAppRefresh
调用一个类函数来检测你所在的国家并添加到一个数组中......一切看起来都很好,我没有错误,但控制台中没有打印任何内容并且无法工作或更新国家/地区列表...

var body: some Scene {
    WindowGroup {
        ContentView()
        
    }
    .modelContainer(container)
    .backgroundTask(.appRefresh("updateCountry")) {
        await locationManager.registerBackgroundTask()
    }
}

有人知道如何解决或者问题出在哪里吗?

swift swiftui background-task background-fetch bgtaskscheduler
2个回答
1
投票
.backgroundTask(.appRefresh("updateCountry"))

的 SwiftUI 版本
 BGTaskScheduler.shared.register

将您的代码更改为类似的内容

.backgroundTask(.appRefresh("updateCountry")) {
    //The task you want performed.
    scheduleBackgroundTask() //Must be sync or async/await, don't use GCD
    detectCountry() //Must be sink or async/await, don't use GCD

}

并且不要忘记第一次致电其他地方的

scheduleBackgroundTask()

在开发模式下,您可以通过在

submit

之后放置断点来按需触发后台任务
do {
    try BGTaskScheduler.shared.submit(request)
    print("Background task scheduled successfully.")

    //ADD breakpoint here
} catch {
    print("Unable to submit task: \(error)")
}

然后,当您运行应用程序并且断点被触发时,请在调试器中键入。

e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"TASK_IDENTIFIER"]

在您的情况下,

TASK_IDENTIFIER
是“updateCountry”。

https://developer.apple.com/documentation/backgroundtasks/starting_and_terminate_tasks_during_development

但需要注意的是......后台任务不会每分钟都运行。您可以建议,但苹果将决定何时运行,不要期望比每小时更频繁。

对于位置之类的信息,您最好使用

LocationManager

https://developer.apple.com/documentation/corelocation/handling_location_updates_in_the_background#

既然您正在监控“国家/地区”,“位置的重大变化”可能是正确的解决方案。

https://developer.apple.com/documentation/corelocation/cllocationmanager/1423531-startmonitoringsignificantlocati


0
投票

各位。 在我使用 SwiftUI 的 ios 应用程序中,我尝试在后台实现获取数据,以便使用来自后端的新数据更新我的应用程序。为了做到这一点,我试图像你一样在后台实现它,但它在我的 iPad 上不起作用。使用

e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"TASK_IDENTIFIER"]
进行调试时效果很好。 我关注了这篇文章 SwiftUI 中的后台任务 这个 SwiftUI 中的新后台任务以及如何测试它 以及这个 WWDC22 视频

这是我为实现它而采取的步骤。

  1. 目标 -> 登录和功能中添加了后台功能,并选择了“后台获取”“后台处理”
  2. 然后在 Info 中添加了 “允许的后台任务调度程序标识符”,我还添加了我的任务 ID。
  3. 我创建了一个异步函数来安排它,并且我还通过通知以防出现问题(这仅用于测试..)。
func sheduleBackgroundTask() async {
   
    let request = BGAppRefreshTaskRequest(identifier: "TASK_IDENTIFIER")
    request.earliestBeginDate = Calendar.current.date(byAdding: .second, value: 30, to: Date())
    do {
        try BGTaskScheduler.shared.submit(request)
        print("DEBUG: Background Task Scheduled!")
    } catch(let error) {
        print("DEBUG: Scheduling Error \(error.localizedDescription)")
        let content = UNMutableNotificationContent()
        content.title = "Background Task Failed!!!"
        content.subtitle = "Message: \(error.localizedDescription)"
        do{
            try await UNUserNotificationCenter.current().add(UNNotificationRequest(identifier: "NOTIFICATION_IDENTIFIER", content: content, trigger: UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)))
        } catch{
            print("DEBUG: Failed notify user \(error.localizedDescription)")
        }
        errorMessage = "Failed failed schedule background task. Message:  \(error.localizedDescription)"
    }
}
  1. 然后我创建了一个函数,从服务器获取数据并使用 Realm 在本地保存获取的数据。

  2. 在应用程序中,我运行通知配置功能并安排后台任务。


    .onAppear{
              configurePushNotification()
              Task{
                await sheduleBackgroundTask()
              }
           }

  1. 然后我在这里注册我的后台任务。
 

.backgroundTask(.appRefresh("TASK_IDENTIFIER")) {
    await sheduleBackgroundTask()
    let _ = await refreshAppData()
 }

我已经在 iPad 上构建并上传了我的应用程序,将其留到周末,但没有任何更改。

© www.soinside.com 2019 - 2024. All rights reserved.