Alamofire : How to handle errors globally

前端 未结 2 433
梦如初夏
梦如初夏 2020-12-07 08:14

My question is quite similar to this one, but for Alamofire : AFNetworking: Handle error globally and repeat request

How to be able to catch globally an error (typic

2条回答
  •  一整个雨季
    2020-12-07 08:57

    in Alamofire 5 you can use RequestInterceptor Here is my error handling for 401 error in one of my projects, every requests that I pass the EnvironmentInterceptor to it the func of retry will be called if the request get to error and also the adapt func can help you to add default value to your requests

    struct EnvironmentInterceptor: RequestInterceptor {
    
    func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (AFResult) -> Void) {
        var adaptedRequest = urlRequest
        guard let token = KeychainWrapper.standard.string(forKey: KeychainsKeys.token.rawValue) else {
            completion(.success(adaptedRequest))
            return
        }
        adaptedRequest.setValue("Bearer \(token)", forHTTPHeaderField: HTTPHeaderField.authentication.rawValue)
        completion(.success(adaptedRequest))
    }
    
    func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
        if let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401 {
            //get token
    
            guard let refreshToken = KeychainWrapper.standard.string(forKey: KeychainsKeys.refreshToken.rawValue) else {
                completion(.doNotRetryWithError(error))
                return
            }
    
            APIDriverAcountClient.refreshToken(refreshToken: refreshToken) { res in
                switch res {
                case .success(let response):
                    let saveAccessToken: Bool = KeychainWrapper.standard.set(response.accessToken, forKey: KeychainsKeys.token.rawValue)
                    let saveRefreshToken: Bool = KeychainWrapper.standard.set(response.refreshToken, forKey: KeychainsKeys.refreshToken.rawValue)
                    let saveUserId: Bool = KeychainWrapper.standard.set(response.userId, forKey: KeychainsKeys.uId.rawValue)
                    print("is accesstoken saved ?: \(saveAccessToken)")
                    print("is refreshToken saved ?: \(saveRefreshToken)")
                    print("is userID saved ?: \(saveUserId)")
                    completion(.retry)
                    break
                case .failure(let err):
                    //TODO logout
                    break
    
                }
    
            }
        } else {
            completion(.doNotRetry)
        }
    }
    

    and you can use it like this :

    @discardableResult
    private static func performRequest(route: ApiDriverTrip, decoder: JSONDecoder = JSONDecoder(), completion: @escaping (AFResult)->Void) -> DataRequest {
    
        return AF.request(route, interceptor: EnvironmentInterceptor())
            .responseDecodable (decoder: decoder){ (response: DataResponse) in
             completion(response.result)
    }
    

提交回复
热议问题