Alamofireのリクエスト/レスポンスが処理されるコードの場所がたくさんあります。
いくつかの断続的な問題が原因で、この各要求は失敗する可能性があります(最も一般的なのは不安定なネットワークです)。
救済の前にリクエストを3回再試行できるようにしたいと思います。
簡単な方法は、そのようなものを持つことです
var errorCount = 0
func requestType1() {
let request = Alamofire.request(...).responseJSON { response in
if (isError(response) && errorCount < 3) {
errorCount += 1
request1()
}
if (isError(response)) {
handleError()
}
handleSuccess()
}
}
しかし、私はこのアプローチA LOTをいくつかの理由で嫌っています。最も明白なのは、要求タイプごとにそのようなコードを実装する必要があることです(そして、15のようなものがあります)。
私は(変更が最小限で邪魔にならないような)何かをする方法があるかどうか好奇心が強い
let request = Alamofire.request(..., **3**)
Swiftで得られる構文糖のビットの1つは、これを使用できることです。
public func updateEvents(someNormalParam: Bool = true, someBlock: (Void->Void))
このような:
updateEvents(someNormalParam: false) {...}
ブロックがupdateEvents関数の()の外にあることに注意してください。これは、ブロックが関数の宣言で最後のものである場合にのみ機能します。
つまり、Alamofireリクエストなどのブロックが発生した場合、それを再試行機能で効果的にラップできます。少し複雑な問題の1つは、ブロック内でブロックを呼び出したい場合です。大したことではない:
func retryWrapper(alamoBlock: (Void->Request)) {
alamoblock().responseJSON() {
//Your retry logic here
}
}
そして、あなたはそのようにそれを使います:
retryWrapper() {
Alamofire.request(method, targetUrl, parameters: parameters, encoding: encoding)
}
つまり、Alamofireの呼び出しを見つけて{}でラップし、前にretryWrapper()を配置するだけです。再試行ロジック自体は一度だけです。
Alamofire 4.0には、使用可能なRequestRetrier
プロトコルがあります。
例:
class OAuth2Handler: RequestAdapter, RequestRetrier {
public func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: RequestRetryCompletion) {
if let response = request.task.response as? HTTPURLResponse, response.statusCode == 401 {
completion(true, 1.0) // retry after 1 second
} else {
completion(false, 0.0) // don't retry
}
// Or do something with the retryCount
// i.e. completion(request.retryCount <= 10, 1.0)
}
}
let sessionManager = SessionManager()
sessionManager.retrier = OAuth2Handler()
sessionManager.request(urlString).responseJSON { response in
debugPrint(response)
}
私も同じ問題を抱えており、RequestRetrier
、should
メソッド、およびrequest.retryCount
を使用して再試行するリクエストを受け取りました。それのようなもの:
// MARK: - RequestRetry
public func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
lock.lock() ; defer { lock.unlock() }
if let response = request.task?.response as? HTTPURLResponse{
if response.statusCode == 401 {
requestsToRetry.append(completion)
getToken { (expires, _) in
_ = SessionCountdownToken.sharedInstance.startCount(expirationTime: expires)
}
} else {
if request.retryCount == 3 { completion(false, 0.0 ); return}
completion(true, 1.0)
return
}
} else {
completion(false, 0.0)
}
}
リクエストリトリエが機能するためのラッパークラスを1つ作成しました。 https://Gist.github.com/daljeetseera/7ce2b53b8a88d8a5e9b172c0495c6455
また、リクエストに必要なセッションマネージャーでリクエストリトリーバーを使用しました。
static let sharedManager: SessionManager = {
let configuration = URLSessionConfiguration.default
let manager = Alamofire.SessionManager(configuration: configuration)
let requestRet = NetworkRequestRetrier()
manager.retrier = requestRet
return manager
}()