[通过手表,我将命令发送到我的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 DTE工程师广泛概述了后台任务处理的要求和极端情况。
此外,Alamofire并不真正支持后台会议。最好将前台会话与后台任务处理结合使用。一旦Alamofire SessionManager
被取消初始化,它开始的所有请求都将被取消,即使是在后台会话中也是如此。
最后,在Alamofire响应处理程序中调用validate()
无效。您应该在添加响应处理程序之前在请求上调用它,因为它可以在调用处理程序之前验证响应。如果您稍后调用它,它将无法将它产生的错误传递给您的响应处理程序。