[英]Pattern for retrying URLSession dataTask?
我对 iOS/Swift 开发还很陌生,我正在开发一个向 REST API 发出多个请求的应用程序。 这是检索“消息”的其中一个调用的示例:
func getMessages() {
let endpoint = "/api/outgoingMessages"
let parameters: [String: Any] = [
"limit" : 100,
"sortOrder" : "ASC"
]
guard let url = createURLWithComponents(endpoint: endpoint, parameters: parameters) else {
print("Failed to create URL!")
return
}
do {
var request = try URLRequest(url: url, method: .get)
let task = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
if let error = error {
print("Request failed with error: \(error)")
// TODO: retry failed request
} else if let data = data, let response = response as? HTTPURLResponse {
if response.statusCode == 200 {
// process data here
} else {
// TODO: retry failed request
}
}
}
task.resume()
} catch {
print("Failed to construct URL: \(error)")
}
}
当然,此请求可能因多种不同原因而失败(服务器无法访问、请求超时、服务器返回 200 以外的其他内容等)。 如果我的请求失败,我希望能够重试它,甚至可能在下一次尝试之前延迟。 我在 Apple 的文档中没有看到关于这种情况的任何指导,但我发现了一些关于 SO 的相关讨论。 不幸的是,这两个都是几年前的,并且在我从未使用过的 Objective-C 中。 在 Swift 中是否有任何常见的模式或实现来做这样的事情?
这个问题是基于意见的一面,而且相当广泛,但我敢打赌大多数是相似的,所以这里是。
对于触发 UI 更改的数据更新:
(例如,填充数据的表或加载图像)一般的经验法则是以无障碍的方式通知用户,如下所示:
然后有一个下拉刷新控件或刷新按钮。
对于不影响用户操作或行为的后台数据更新:
您可以根据代码轻松地将重试计数器添加到您的请求结果中 - 但我会小心使用这个计数器并构建一些更智能的逻辑。 例如,给定以下状态代码,您可能希望以不同的方式处理事情:
5xx:您的服务器有问题。 您可能希望将重试延迟 30 秒或一分钟,但如果发生 3 或 4 次,您将希望停止重试后端。
401:经过身份验证的用户可能不再有权调用您的 API。 你根本不想重试; 相反,您可能希望将用户注销,以便下次他们使用您的应用程序时,系统会提示他们重新进行身份验证。
网络超时/丢失连接:在重新建立连接之前,重试无关紧要。 您可以围绕可达性处理程序编写一些逻辑,以便在下一次网络连接可用时对后台请求进行排队。
最后,正如我们在评论中提到的,您可能想要查看通知驱动的后台应用程序刷新。 在这里,您可以发送通知来告诉应用程序进行自我更新,而不是轮询服务器以获取更改,即使它不在前台运行。 如果您足够聪明,您可以让您的服务器向您的应用程序重复通知,直到应用程序确认收到 - 这以一致的方式解决了连接故障和无数其他服务器响应错误代码。
我将处理重试的三种方法分类:
waitsForConnectivity
(iOS 11+) 属性,您可以在URLSession
配置上设置该URLSession
。 通过设置它,当任务正在等待网络连接时,您会通过URLSessionDataDelegate
。 您可以利用这个机会启用离线模式或向用户显示某些内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.