Alamofire 自定义响应从 Alamofire v1.3 迁移到 3.0(和 Swift 2 语法)
Posted
技术标签:
【中文标题】Alamofire 自定义响应从 Alamofire v1.3 迁移到 3.0(和 Swift 2 语法)【英文标题】:Alamofire custom reponse migration from Alamofire v1.3 to 3.0 (and Swift 2 syntax) 【发布时间】:2015-11-17 15:17:26 【问题描述】:我正在将使用 Alamofire 1.3 的项目从 Swift 1.1 转换为 Swift 2.0。 因为这个版本的 Alamofire 与 Swift 2.0 不兼容,所以我切换到了 Alamofire 的最新版本(3.1.x)。
但是这破坏了代码,我现在收到错误消息
“不能调用非函数类型'NSHTTPURLResponse'的值?'”
这是由于我创建自定义“responseShop”Alamofire.Request 的扩展。
如何才能将此 Alamofire.Request 扩展正确转换为 Alamofire 3.x/Swift 2.0 语法?
extension Alamofire.Request
func responseShop(options: NSJSONReadingOptions = .AllowFragments, var errorHandler:ProtocolWebServiceErrorHandler?, completionHandler: (ShopCallResult?, WebServiceErrorCode) -> Void ) -> Self
objc_sync_enter(communicationLockObj)
return response(serializer: Request.JSONResponseSerializer(options: options), completionHandler:
(request, response, JSON, error) in
log.verbose("\(JSON)")
//network error?
if let error = error
//is it cancelled?
if error.code == -999
dispatch_async(dispatch_get_main_queue())
//call handler with cancelled code
completionHandler(nil, WebServiceErrorCode.requestCancelled)
objc_sync_exit(communicationLockObj)
return
dispatch_async(dispatch_get_main_queue())
errorHandler?.handleWebServiceError(WebServiceErrorCode.connectError, errorText : error.localizedDescription, request: request, json: JSON)
//call and supply org error
completionHandler(nil, WebServiceErrorCode.connectError)
objc_sync_exit(communicationLockObj)
return
if JSON == nil
dispatch_async(dispatch_get_main_queue())
errorHandler?.handleWebServiceError(WebServiceErrorCode.jsonNil, errorText: nil, request: request, json: JSON)
//call and supply org error
completionHandler(nil, WebServiceErrorCode.jsonNil)
objc_sync_exit(communicationLockObj)
return
//api return error?
let callResult = ShopCallResult(json: JSON!)
if callResult.statusCode.failed
dispatch_async(dispatch_get_main_queue())
errorHandler?.handleWebServiceError(callResult.statusCode, errorText: callResult.statusCode.localizedText, request: request, json: JSON)
completionHandler(callResult, callResult.statusCode)
objc_sync_exit(communicationLockObj)
return
//no error
dispatch_async(dispatch_get_main_queue())
completionHandler(callResult, WebServiceErrorCode.OK)
objc_sync_exit(communicationLockObj)
)
return self
【问题讨论】:
您不再需要指定 Json 序列化程序。尝试用responseJSON response in debugPrint(response)
替换response
看看这里的例子github.com/Alamofire/Alamofire/blob/master/Documentation/…
【参考方案1】:
根据@ProblemSolver 的反馈,我设法转换了代码,现在看起来像这样:
extension Alamofire.Request
func responseShop(queue: dispatch_queue_t? = nil, options: NSJSONReadingOptions = .AllowFragments, errorHandler:ProtocolWebServiceErrorHandler?, completionHandler: (ShopCallResult?, WebServiceErrorCode) -> Void ) -> Self
//enter thread protected area...
objc_sync_enter(communicationLockObj)
return responseJSON()
response in
switch response.result
case .Success(let JSON):
//log json in verbose mode
log.verbose("\(JSON)")
//parse the returned json
let callResult = ShopCallResult(json: JSON)
//is it failed?
if callResult.statusCode.failed
//call supplied error handler on the main thread
dispatch_async(dispatch_get_main_queue())
errorHandler?.handleWebServiceError(callResult.statusCode, errorText: callResult.statusCode.localizedText, request: self.request!, json: JSON)
completionHandler(callResult, callResult.statusCode)
//release the lock
objc_sync_exit(communicationLockObj)
//processing done!
return
//no error call handler on main thread
dispatch_async(dispatch_get_main_queue())
completionHandler(callResult, WebServiceErrorCode.OK)
//release the lock
objc_sync_exit(communicationLockObj)
case .Failure(let error):
//WARNING: cancelled is still error code 999?
//is it cancelled?
if error.code == -999
//just call the completion handler
dispatch_async(dispatch_get_main_queue())
//call handler with cancelled code
completionHandler(nil, WebServiceErrorCode.requestCancelled)
//release the lock
objc_sync_exit(communicationLockObj)
//stop furhter processing
return
//error with the json?
if error.code == Alamofire.Error.Code.JSONSerializationFailed .rawValue
//call the error handler
dispatch_async(dispatch_get_main_queue())
errorHandler?.handleWebServiceError(WebServiceErrorCode.jsonNil, errorText: nil, request: self.request!, json: nil)
//call and supply org error
completionHandler(nil, WebServiceErrorCode.jsonNil)
//release the lock
objc_sync_exit(communicationLockObj)
//stop further processing
return
//must be some other kind of network error
dispatch_async(dispatch_get_main_queue())
log.error("\(error)")
//so call the error handler
errorHandler?.handleWebServiceError(WebServiceErrorCode.connectError, errorText : error.localizedDescription, request: self.request!, json: nil)
//call and supply org error
completionHandler(nil, WebServiceErrorCode.connectError)
//release the lock
objc_sync_exit(communicationLockObj)
【讨论】:
我不太确定锁定的原因,但您可以使用Swift 2
中的 defer
语法进行 objc_sync_exit
调用。而不是重复 5 次。
锁定背后的想法是一次只能激活一个 Web 服务调用(它们应该被序列化......)。老实说,不确定锁定是否能实现这一点......因为我们已经在使用队列以上是关于Alamofire 自定义响应从 Alamofire v1.3 迁移到 3.0(和 Swift 2 语法)的主要内容,如果未能解决你的问题,请参考以下文章
自定义序列化在 Alamofire 4.0 中发现不正确的“响应”
swift 具有Argo和自定义错误类型的Generic Alamofire响应序列化程序
Alamofire - 如何从 AFError 获取 API 错误