Swift后台App刷新任务无法运行问题排查(Swift 5.7+Scene)
Swift 5.7 + Scene架构下后台HTTP接口调用异常排查
我用Swift 5.7结合Scene架构开发App,希望在App进入后台时调用HTTP接口,但当前实现无法正常工作。网上大多资源都过时了,找不到适配的示例。我通过自定义URLSessionDataDelegate实现API回调,知道要在后台任务里用dataTask(因为async/await在后台环境下无法工作),另外还想实现任务完成后自动提交新的后台任务,但这部分还没做。
目前遇到两个核心问题:
- 猜测因为
Service().callAPI()不是异步执行的,task.setTaskCompleted(success: true)会在dataTask完成前就执行,导致接口的处理逻辑没跑完就提前结束了。我尝试把BG任务传入Service,想在代理方法里调用setTaskCompleted,但没成功。 - 频繁出现错误:
NSURLErrorDomain Code=-997 "Lost connection to background transfer service"
当前代码实现
AppDelegate.swift
let bgTaskIdentifier = "task.identifier" class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { BGTaskScheduler.shared.register(forTaskWithIdentifier: bgTaskIdentifier, using: nil) { task in self.handleAppRefresh(task as! BGAppRefreshTask) } print("Registered background task (\(bgTaskIdentifier))") return true } func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) } func handleAppRefresh(_ task: BGAppRefreshTask) { task.expirationHandler = { task.setTaskCompleted(success: false) } Service().callAPI() task.setTaskCompleted(success: true) } }
SceneDelegate.swift
class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let _ = (scene as? UIWindowScene) else { return } } func sceneDidEnterBackground(_ scene: UIScene) { submitBackgroundTask() } func submitBackgroundTask() { do { let taskRequest = BGAppRefreshTaskRequest(identifier: bgTaskIdentifier) taskRequest.earliestBeginDate = Date(timeIntervalSinceNow: 10) try BGTaskScheduler.shared.submit(taskRequest) logger.info("Submitted background task request") } catch { logger.info("Failed to submit task request") } } }
Service.swift
class Service: NSObject, URLSessionDataDelegate { func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) { let decoder = JSONDecoder() // Decode here and do stuff with response data } func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) { guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else { logger.info("Request failed") completionHandler(.cancel) return } completionHandler(.allow) } func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { if error != nil { logger.info("Failed: \(error!)") } } func callAPI() { let url = URL(string: "https://example.com")! var request = URLRequest(url: url) let config = URLSessionConfiguration.background(withIdentifier: bgTaskIdentifier) let session = URLSession(configuration: config, delegate: self, delegateQueue: nil) session.dataTask(with: request).resume() } }
内容的提问来源于stack exchange,提问作者Mega
相关产品推荐
相关产品推荐

