Ios 有没有办法通过重试来执行Alamofire请求

Ios 有没有办法通过重试来执行Alamofire请求,ios,swift,alamofire,Ios,Swift,Alamofire,我在代码中有很多地方处理Alamofire请求/响应 每个请求都可能由于某些间歇性问题而失败(最常见的是网络故障) 我希望能够在退出之前重试请求3次 最简单的方法就是拥有这样的东西 var errorCount = 0 func requestType1() { let request = Alamofire.request(...).responseJSON { response in if (isError(response) && errorCount

我在代码中有很多地方处理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()
   }
}

Swift的语法优势之一是你可以使用:

public func updateEvents(someNormalParam: Bool = true, someBlock: (Void->Void))
像这样:

updateEvents(someNormalParam: false) {...}
注意,该块位于updateEvents函数()的外部,与您通常期望的相反。只有当块是函数声明中的最后一项时,它才起作用

这意味着,如果您碰巧有一个块,比如Alamofire请求,您可以使用重试功能有效地将其包装起来。一个稍微复杂的问题是要调用块中的块。没什么大不了的:

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)
}
类OAuth2Handler:RequestAdapter、RequestRetrier{ public func应该(manager:SessionManager,重试请求:request,错误:error,完成:RequestRetryCompletion){ 如果让response=request.task.response为?HTTPURLResponse,则response.statusCode==401{ 完成(true,1.0)//1秒后重试 }否则{ 完成(false,0.0)//不重试 } //或者用retryCount做点什么
//例如,完成(request.retryCount我也遇到了同样的问题,我使用
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)
    }
}

我已经为请求检索器创建了一个包装类。

并使用请求所需的会话管理器中的请求检索器

static let sharedManager: SessionManager = {
        let configuration = URLSessionConfiguration.default
        let manager = Alamofire.SessionManager(configuration: configuration)
        let requestRet = NetworkRequestRetrier()
        manager.retrier = requestRet
        return manager
    }()


你能制作一个将请求作为结束块的包装器吗?这样,你就不用直接调用请求,而是在块中有相同的请求代码,但调用包装器?这样更容易更改代码。卡洛斯。我认为你是对的。我忽略了这一点:).你想写下来作为回答吗?当然,给我一点时间,我会写的that@VictorRonin你能解释一下你是怎么得到它的吗?我有点困惑我们的反应是什么这里?我有点生疏,但它看起来像是块返回一个请求,它有一个函数将其转换为JSONCant我们使用requestRetrier?不知道。自从我写这篇文章以来,事情可能已经开始了。我正在使用Alamofire.Request…方法,以及我如何适应requestRetrier?现在我使用APIRouter和UrlRequestConverable方法,AF.request(request).validate().responseJSON{(response)……我正在设置APIRouter中的标头……使用Retrier..看起来我需要改变我的整个方法?或者有没有简单的方法来使用Retrier并将影响降到最低..我使用这种方法@anoop4real请向其他人提出一个新的问题,以便向你提供建议,以便评论与此答案相关第一行的锁是什么?@jayantrawat我猜它是一个
NSRecursiveLock()
实例
static let sharedManager: SessionManager = {
        let configuration = URLSessionConfiguration.default
        let manager = Alamofire.SessionManager(configuration: configuration)
        let requestRet = NetworkRequestRetrier()
        manager.retrier = requestRet
        return manager
    }()