从我的手表,我发送命令到我的iOS应用程序。不清楚原因,但如果应用程序在后台,我可以看到一些错误:Error Domain=NSURLErrorDomain Code=-997 "Lost connection to background transfer service"
Can't end BackgroundTask: no background task exists with identifier 383 (0x17f), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.
我已经尝试将配置更改为后台,请为我的配置提供正确的标识符。
我的SessionManager的静态或延迟实现。
计算进程中的deinit。
网络会话管理器
static var sessionManager: SessionManager = {
let configuration = URLSessionConfiguration.background(withIdentifier: UUID().uuidString + ".WatchOS_Background")
configuration.httpShouldSetCookies = false
configuration.httpMaximumConnectionsPerHost = 4
configuration.timeoutIntervalForRequest = 50
configuration.networkServiceType = .background
configuration.isDiscretionary = false
configuration.shouldUseExtendedBackgroundIdleMode = true
if #available(iOS 13.0, *) {
configuration.allowsExpensiveNetworkAccess = true
configuration.allowsConstrainedNetworkAccess = true
}
let sessionManager = Alamofire.SessionManager(configuration: configuration)
sessionManager.delegate.sessionDidBecomeInvalidWithError = { _, error in
if let error = error {
print(error)
}
}
sessionManager.delegate.taskDidComplete = { _, task, error in
if let error = error {
print(error)
}
}
return sessionManager
}()
请求示例
func getListFromServer(completion: @escaping (ServiceResponse<[Model1]>) -> Void) {
let header: HTTPHeaders = ["User-Agent": UserAgentHelper.fullUserAgentString]
request("/api/1/XXXX", method: .get, parameters: nil, encoding: nil, headers: header).responseData { [weak self] response in
guard let strongSelf = self else { return }
completion(strongSelf.completionResponse(response))
}
}
请求方法
@discardableResult private func request(
_ path: String,
method: HTTPMethod,
parameters: Parameters? = nil,
encoding: ParameterEncoding? = nil,
headers: HTTPHeaders? = nil)
-> DataRequest {
let userEncoding = encoding ?? self.defaultEncoding
let task = beginBackgroundTask()
let dataRequest = NetworkService.sessionManager.request("\(API)\(path)",
method: method,
parameters: parameters,
encoding: userEncoding,
headers: headers)
dataRequest.validate()
self.endBackgroundTask(taskID: task)
return dataRequest
}
开始和结束后台任务
func beginBackgroundTask() -> UIBackgroundTaskIdentifier {
return UIApplication.shared.beginBackgroundTask(withName: "Background_API", expirationHandler: {})
}
func endBackgroundTask(taskID: UIBackgroundTaskIdentifier) {
UIApplication.shared.endBackgroundTask(taskID)
}
我希望有一个适当的实现从您和一个稳定的请求生命周期。
非常感谢您的帮助,并为缺少技术术语提前表示歉意。
最佳答案
你的核心问题是没有正确处理后台任务的过期时间。必须在任务的过期处理程序中显式结束任务:
let task = UIApplication.shared.beginBackgroundTask(withName: "Background_API") {
UIApplication.shared.endBackgroundTask(task)
}
我建议您阅读更多的here,其中一位Apple DTS工程师已经广泛地概述了后台任务处理的需求和边缘案例。
另外,Alamofire并不真正支持后台会话。在后台任务处理中使用前台会话可能是最好的选择。一旦Alamofire
SessionManager
被取消初始化,它启动的任何请求都将被取消,即使是后台会话。最后,在Alamofire响应处理程序中调用
validate()
是无效的。您应该在添加响应处理程序之前对请求调用它,因为它在调用处理程序之前验证响应。如果您在之后调用它,它将无法将它产生的错误传递给您的响应处理程序。