2016-09-26 2 views
4

Я использую SessionManager Alamofire для запросов на мои услуги API.Alamofire, Session Manager limit retry count

Есть ли способ ограничить количество повторных попыток в Alamofire?

Я использую новые протоколы RequestAdapter и RequestTrier, чтобы обеспечить механизм повтора в Alamofire v4.

Я хочу ограничить количество попыток до 5. Если после 5 повторных попыток новый запрос не должен быть выполнен.

class VMRetrier: RequestAdapter, RequestRetrier { 

public func adapt(_ urlRequest: URLRequest) throws -> URLRequest { 
    return urlRequest; 
} 

func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) { 

    if let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401 { 
     VMLogger.shared.debug(message: "Trying to get a token") 
     let _ = AuthService.shared.login(email: "[email protected]", password: "test34") 
          .then(execute: { (response) in 
           completion(true, 0.0) 
          }) 
    } 
    else { 
     completion(false, 0.0) 
    } 
} } 

Использование:

internal let sessionManager = SessionManager() 

override init() { 
    super.init() 
    sessionManager.adapter = VMRequestAdapter() 
    sessionManager.retrier = VMRetrier() 
} 

UPDATE Существует новый совершить в alamofire, чтобы обеспечить вариант подсчета повторных попыток. Alamofire Commit

+0

Вы нашли какие-либо решения? – Footjy

+0

см. Мое обновление – aymeba

ответ

3

Я решил это с протоколом Alamofire в RequestRetrier:

class Retrier: RequestRetrier { 

    var defaultRetryCount = 4 
    private var requestsAndRetryCounts: [(Request, Int)] = [] 
    private var lock = NSLock() 

    private func index(request: Request) -> Int? { 
     return requestsAndRetryCounts.index(where: { $0.0 === request }) 
    } 

    func addRetryInfo(request: Request, retryCount: Int? = nil) { 
     lock.lock() ; defer { lock.unlock() } 
     guard index(request: request) == nil else { print("ERROR addRetryInfo called for already tracked request"); return } 

     requestsAndRetryCounts.append((request, retryCount ?? defaultRetryCount)) 
    } 

    func deleteRetryInfo(request: Request) { 
     lock.lock() ; defer { lock.unlock() } 
     guard let index = index(request: request) else { print("ERROR deleteRetryInfo called for not tracked request"); return } 

     requestsAndRetryCounts.remove(at: index) 
    } 

    func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion){ 

     lock.lock() ; defer { lock.unlock() } 

     guard let index = index(request: request) else { completion(false, 0); return } 
     let (request, retryCount) = requestsAndRetryCounts[index] 

     if retryCount == 0 { 
      completion(false, 0) 
     } else { 
      requestsAndRetryCounts[index] = (request, retryCount - 1) 
      completion(true, 0.5) 
     } 
    } 
} 

должны использоваться таким образом:

let manager = SessionManager() 
let retrier = Retrier() 
// ... 
manager.retrier = retrier 

затем

let request = manager.request(urlString, method: method, parameters: parameters, encoding: JSONEncoding.default, headers: headers) 

retrier.addRetryInfo(request: request) 

request.response { r in 
    self.retrier.deleteRetryInfo(request: request) 
}.responseApiJSON { (r: DataResponse<JSONObject>) in 
    // You code here 
} 
+0

Это было бы неплохо, если бы он был встроен в проект Alamofire – neoneye

+1

Что делать, если я не использую какой-либо менеджер сеансов здесь? Как использовать запрос-запрос – Ranjit