Alamofire:如何在全球范围内处理401?

时间:2016-03-17 13:37:32

标签: ios swift networking alamofire

我正在尝试构建一个管理我的项目网络调用的类。到目前为止,我的意思是在全球范围内处理错误,一切都很好。我创造了两个功能;发布请求postRequest(:_)和获取请求getRequests(:_)。 Datamaker用于返回数据,如URL,参数,标题等,数据解析器函数用于解析响应数据,最后用于解决称为errorHandler()的错误的函数。

当我调用请求函数时,我给出一个参数来帮助它应该发出哪个请求。在函数中,它首先调用数据制作者获取数据,然后使用Alamofire发出请求,最后如果请求成功,则调用dataparser和onSuccess(data:)闭包,如果不是,则调用{{ 1}}和errorHandler(statusCode:)关闭。

我在onFailure(message:)中放了一个开关块,并为其参数提供了statusCode。在errorHandler中,我调用了case 401,并在其中完成了Token().refresh()的完成。在errorHanlder / postRequest的完成块中,我使用相同的参数再次调用errorHandler。它没用。我不知道为什么,它每次都进入无限循环并连续提出请求。

所以我决定尝试cnoonpostRequest课程(可在此链接中找到; Alamofire : How to handle errors globally)。我稍微改了一下(添加了一个新的参数作为标题,并将AuthorizationManager的类型更改为NetworkSuccessHandler)。这是新表格:

NSData

在我的public class AuthorizationManager: Manager { public typealias NetworkSuccessHandler = (NSData?) -> Void public typealias NetworkFailureHandler = (NSHTTPURLResponse?, AnyObject?, NSError) -> Void private typealias CachedTask = (NSHTTPURLResponse?, AnyObject?, NSError?) -> Void private var cachedTasks = Array<CachedTask>() private var isRefreshing = false public func startRequest( method method: Alamofire.Method, URLString: URLStringConvertible, parameters: [String: AnyObject]?, encoding: ParameterEncoding, headers: [String:String]?, success: NetworkSuccessHandler?, failure: NetworkFailureHandler?) -> Request? { let cachedTask: CachedTask = { [weak self] URLResponse, data, error in guard let strongSelf = self else { return } if let error = error { failure?(URLResponse, data, error) } else { strongSelf.startRequest( method: method, URLString: URLString, parameters: parameters, encoding: encoding, headers: headers, success: success, failure: failure ) } } if self.isRefreshing { self.cachedTasks.append(cachedTask) return nil } // Append your auth tokens here to your parameters let request = self.request(method, URLString, parameters: parameters, encoding: encoding, headers: headers) request.response { [weak self] request, response, data, error in guard let strongSelf = self else { return } if let response = response where response.statusCode == 401 { strongSelf.cachedTasks.append(cachedTask) strongSelf.refreshTokens() return } if let error = error { failure?(response, data, error) } else { success?(data) } } return request } func refreshTokens() { self.isRefreshing = true // Make the refresh call and run the following in the success closure to restart the cached tasks Token().refresh { () -> () in let cachedTaskCopy = self.cachedTasks self.cachedTasks.removeAll() cachedTaskCopy.map { $0(nil, nil, nil) } self.isRefreshing = false } } } 中调用它:

postRequest

func postRequest(requestType: postRequestType, additionalParameters: [String]?, onSuccess: onSuccessRequest = {_ in }, onFailure: onFailureRequest = {_ in }){ print("post") let requestData = returnStaticDataForPostRequest(requestType, additionalParameters: additionalParameters) let Manager = AuthorizationManager() Manager.startRequest(method: .POST, URLString: requestData.0, parameters: requestData.2, encoding: requestData.3, headers: requestData.1, success: { (data) -> Void in print("Manager") let json = JSON(data: data!) print(json) dataParserForPostRequests(json, parseForWhat: requestType) onSuccess(json: json) }) { (response, message, error) -> Void in print(error) } } 中使用postRequests

ViewController

这是目前的状态。当我运行代码并尝试登录postRequest(.LOGIN, additionalParameters: ["asdasd", "asdasd"], onSuccess: { (json) -> () in print(">>>login_try_succeeded") self.performSegueWithIdentifier("LoginToMain", sender: self) }) { (errorCode) -> () in print(">>>login_try_failed(\(errorCode))") } 时不起作用。它只是打印;

AuthorizationManager

最后,我不知道它是否相关,但此行有黄色警告:

post

cachedTaskCopy.map { $0(nil, nil, nil) }

总结一下,我需要弄清楚如何处理401,我知道如何以不同的方式使用"Result of call to 'map' is unused"

修改

我尝试直接从AuthorizationManager运行此代码,但它根本不起作用。这就像代码是不可见的。

ViewController

1 个答案:

答案 0 :(得分:2)

可能是您的AuthorizationManager在最初尝试发送请求后未持久存在。

通常情况下避免单例模式是一种好习惯,但这不是一个坏的情况:

public class AuthorizationManager: Manager {
    static let shared = AuthorizationManager()
    // ...the rest of your class
}

在调用您的请求时,请使用此单例实例,而不是实例化新的AuthorizationManager,如

AuthorizationManager.shared.startRequest(method: .POST, ...etc...

我猜这可能是个问题,因为在两种情况下创建AuthorizationManager时都没有主动保留该对象。可以创建管理器,运行请求,然后在cachedTask之前或甚至在完成处理之前取消分配,在这种情况下,guard let strongSelf = self else { return }只返回而不运行任何完成或cachedTasks。

希望这会有所帮助。如果 问题,则该单例解决方案应该非常简单。