当我调用请求函数时,我给出一个参数来帮助它应该做出哪个请求.在函数中,它首先调用数据制作者获取数据,然后使用Alamofire发出请求,最后如果请求成功,则调用dataparser和onSuccess(data :)闭包,如果不是,则调用errorHandler(statusCode :)和onFailure(消息:)关闭.
我在errorHandler中放了一个switch块,并为其参数提供了statusCode.在401的情况下,我调用了Token().refresh()并在其中完成了名为errorHanlder的完成.在postRequest / errorHandler的完成块中,我使用相同的参数再次调用postRequest.它没用.我不知道为什么,它每次都进入无限循环并连续提出请求.
所以我决定尝试cnoon的AuthorizationManager类(可以在这个链接中找到; Alamofire : How to handle errors globally).我稍微改了一下(添加了一个新的参数作为标题,并将NetworkSuccessHandler的类型更改为NSData).这是新表格:
public class AuthorizationManager: Manager { public typealias NetworkSuccessHandler = (NSData?) -> Void public typealias NetworkFailureHandler = (NSHTTPURLResponse?,AnyObject?,NSError) -> Void private typealias CachedTask = (NSHTTPURLResponse?,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,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,headers: headers) request.response { [weak self] request,response,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,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) } }
并在ViewController中使用postRequests:
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) }
说“调用’地图’的结果未使用”
总结一下,我需要弄清楚如何处理401,我知道如何以不同的方式使用AuthorizationManager.
编辑:
我尝试直接从ViewController运行此代码,但它根本不起作用.这就像代码是不可见的.
AuthorizationManager().startRequest(method: .POST,URLString: NSURL(string: "http://server.url/token")!,parameters: ["":""],encoding: .JSON,headers: ["":""],success: { (data) -> Void in print(data) }) { (response,error) -> Void in print(error) print("asdasd") }
解决方法
通常,避免使用单例模式是一种好习惯,但这不是一个不好的情况:
public class AuthorizationManager: Manager { static let shared = AuthorizationManager() // ...the rest of your class }
在调用您的请求时,请使用此单例实例,而不是实例化新的AuthorizationManager
AuthorizationManager.shared.startRequest(method: .POST,...etc...
我猜这可能是个问题,因为在这两种情况下创建AuthorizationManager时都没有主动保留该对象.可以创建管理器,运行请求,然后在cachedTask之前或甚至在完成处理之前解除分配,在这种情况下,你的后卫让strongSelf = self else {return}只返回而不运行任何完成或cachedTasks.
希望这会有所帮助.如果这是问题,那么单例解决方案应该非常简单.