我正在使用新的iOS13后台任务框架以及BGAppRefreshTask类型的实现。我的问题是,即使等待了几个小时,我的设备也永远不会调用任务,但是我能够使用调用_simulateLaunchForTaskWithIdentifier的调试器技巧成功运行代码。
我已经设置了以下内容:
我已经从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/