[英]Pattern for retrying URLSession dataTask?
I'm fairly new to iOS/Swift development and I'm working on an app that makes several requests to a REST API.我对 iOS/Swift 开发还很陌生,我正在开发一个向 REST API 发出多个请求的应用程序。 Here's a sample of one of those calls which retrieves "messages":
这是检索“消息”的其中一个调用的示例:
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)")
}
}
Of course, it's possible for this request to fail for a number of different reasons (server is unreachable, request timed out, server returns something other than 200, etc).当然,此请求可能因多种不同原因而失败(服务器无法访问、请求超时、服务器返回 200 以外的其他内容等)。 If my request fails, I'd like to have the ability to retry it, perhaps even with a delay before the next attempt.
如果我的请求失败,我希望能够重试它,甚至可能在下一次尝试之前延迟。 I didn't see any guidance on this scenario in Apple's documentation but I found a couple of related discussions on SO.
我在 Apple 的文档中没有看到关于这种情况的任何指导,但我发现了一些关于 SO 的相关讨论。 Unfortunately, both of those were a few years old and in Objective-C which I've never worked with.
不幸的是,这两个都是几年前的,并且在我从未使用过的 Objective-C 中。 Are there any common patterns or implementations for doing something like this in Swift?
在 Swift 中是否有任何常见的模式或实现来做这样的事情?
This question is airing on the side of opinion-based, and is rather broad, but I bet most are similar, so here goes.这个问题是基于意见的一面,而且相当广泛,但我敢打赌大多数是相似的,所以这里是。
For data updates that trigger UI changes:对于触发 UI 更改的数据更新:
(eg a table populated with data, or images loading) the general rule of thumb is to notify the user in a non-obstructing way, like so: (例如,填充数据的表或加载图像)一般的经验法则是以无障碍的方式通知用户,如下所示:
And then have a pull-to-refresh control or a refresh button.然后有一个下拉刷新控件或刷新按钮。
For background data updates that don't impact the user's actions or behavior:对于不影响用户操作或行为的后台数据更新:
You could easily add a retry counter into your request result depending on the code - but I'd be careful with this one and build out some more intelligent logic.您可以根据代码轻松地将重试计数器添加到您的请求结果中 - 但我会小心使用这个计数器并构建一些更智能的逻辑。 For example, given the following status codes, you might want to handle things differently:
例如,给定以下状态代码,您可能希望以不同的方式处理事情:
5xx: Something is wrong with your server. 5xx:您的服务器有问题。 You may want to delay the retry for 30s or a minute, but if it happens 3 or 4 times, you're going to want to stop hammering your back end.
您可能希望将重试延迟 30 秒或一分钟,但如果发生 3 或 4 次,您将希望停止重试后端。
401: The authenticated user may no longer be authorized to call your API. 401:经过身份验证的用户可能不再有权调用您的 API。 You're not going to want to retry this at all;
你根本不想重试; instead, you'd probably want to log the user out so the next time they use your app they're prompted to re-authenticate.
相反,您可能希望将用户注销,以便下次他们使用您的应用程序时,系统会提示他们重新进行身份验证。
Network time-out/lost connection: Retrying is irrelevant until connection is re-established.网络超时/丢失连接:在重新建立连接之前,重试无关紧要。 You could write some logic around your reachability handler to queue background requests for actioning the next time network connectivity is available.
您可以围绕可达性处理程序编写一些逻辑,以便在下一次网络连接可用时对后台请求进行排队。
And finally, as we touched on in the comments, you might want to look at notification-driven background app refreshing.最后,正如我们在评论中提到的,您可能想要查看通知驱动的后台应用程序刷新。 This is where instead of polling your server for changes, you can send a notification to tell the app to update itself even when it's not running in the foreground.
在这里,您可以发送通知来告诉应用程序进行自我更新,而不是轮询服务器以获取更改,即使它不在前台运行。 If you're clever enough, you can have your server repeat notifications to your app until the app has confirmed receipt - this solves for connectivity failures and a myriad of other server response error codes in a consistent way.
如果您足够聪明,您可以让您的服务器向您的应用程序重复通知,直到应用程序确认收到 - 这以一致的方式解决了连接故障和无数其他服务器响应错误代码。
I'd categorize three methods for handling retry:我将处理重试的三种方法分类:
waitsForConnectivity
(iOS 11+) property that you can set on the URLSession
configuration.waitsForConnectivity
(iOS 11+) 属性,您可以在URLSession
配置上设置该URLSession
。 By setting it, you are alerted via the URLSessionDataDelegate
when a task is waiting for a network connection.URLSessionDataDelegate
。 You could use that opportunity to enable an offline mode or display something to the user.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.