Swift后台执行



我在AWS上有一个由HTTPPost请求触发的步骤函数。该功能可能需要几秒钟才能完成。如果用户将应用程序放回后台,我希望继续执行,并在用户将应用软件放回前台后(如果执行完成(正确导航到下一个屏幕。

我的API客户端端点如下所示:

func connect<OutputType: Decodable>(to request: URLRequestConvertible, decoder: JSONDecoder) -> AnyPublisher<Result<OutputType, Error>, Never> {
var request = request.asURLRequest()

if let token: String = KeychainWrapper.standard.string(forKey: "apiToken") {
request.addValue(token, forHTTPHeaderField: "Authorization")
}

let configuration = URLSessionConfiguration.default
configuration.waitsForConnectivity = true
let session = URLSession(configuration: configuration)

return session.dataTaskPublisher(for: request)
.tryMap({ (data, response) -> Data in
guard let response = response as? HTTPURLResponse else { throw NetworkError.invalidResponse }
guard 200..<300 ~= response.statusCode else {
throw NetworkError.invalidStatusCode(statusCode: response.statusCode)

}
return data
})
.decode(type: OutputType.self, decoder: decoder)
.map(Result.success)
.catch { error -> Just<Result<OutputType, Error>> in Just(.failure(error)) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}

我想知道实现这一呼吁的最佳实践。我目前正在使用下面的beginBackgroundTask。

func makeRequest() {
DispatchQueue.global(qos: .userInitiated).async {
self.backgroundTaskID = UIApplication.shared.beginBackgroundTask (withName: "Request Name") {
UIApplication.shared.endBackgroundTask(self.backgroundTaskID!)
self.backgroundTaskID = .invalid
}
<implementation>
}
}

然而,implementation只有在我嵌套了DispatchQueue.main.async块的情况下才有效,在这些块中,我在发出HTTP请求后执行更多的逻辑(比如在收到响应后确定下一个屏幕的导航(。

这是最好的方法吗?在DispatchQueue.global块中有几个不同的嵌套DispatchQueQueue.main.async块可以吗?我应该将.receive(on: )发布到DispatchQueue.global吗?

您根本不必将此后台任务分派到后台队列。(不要将"后台任务"(指应用程序状态(与"后台队列"(指使用哪些线程(混为一谈。(

此外,正如文档所说,过期处理程序闭包在主线程上运行:

系统在主线程上同步调用处理程序,暂时阻止应用程序的挂起。

因此,无论如何,您确实希望在主线程上保留与backgroundTaskID的所有交互,否则您将不得不实现一些其他同步机制。


作为一种良好的做法,请确保在异步请求完成时结束后台任务(而不是依赖于过期/超时关闭(。

相关内容

  • 没有找到相关文章

最新更新