了解Alamofire的响应对象序列化使用闭包

时间:2015-06-23 06:39:28

标签: swift serialization alamofire

我试图理解下面这个Ray Wenderlich tutorial的例子。我的主要困惑不在于什么(以方便的方式将JSON数据反序列化到您自己的对象中)它正在做什么,但 它在做什么它。我所做的就是解释我理解的代码片段,但我的困惑源于completionHandler闭包及其类型定义。在我最初接受代码所做的事之后,我会强调这一点。

首先是行号的代码段:

  1 @objc public protocol ResponseObjectSerializable {
  2   init(response: NSHTTPURLResponse, representation: AnyObject)
  3 }
  4
  5 extension Alamofire.Request {
  6   public func responseObject<T: ResponseObjectSerializable>(completionHandler: (NSURLRequest, NSHTTPURLResponse?, T?, NSError?) -> Void) -> Self {
  7     let serializer: Serializer = { (request, response, data) in
  8       let JSONSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
  9       let (JSON: AnyObject?, serializationError) = JSONSerializer(request, response, data)
 10       if response != nil && JSON != nil {
 11         return (T(response: response!, representation: JSON!), nil)
 12       } else {
 13         return (nil, serializationError)
 14       }
 15     }
 16
 17     return response(serializer: serializer, completionHandler: { (request, response, object, error) in
 18       completionHandler(request, response, object as? T, error)
 19     })
 20   }
 21 }

第6行 - 这里我们声明一个接受&#34; completionHandler&#34;的通用函数(responseObject)。签名为(NSURLRequest, NSHTTPURLResponse?, T?, NSError?) -> Void的封闭。然后它返回它自己的类-> self的实例。

第7到第15行 - 这里我们使用Serializer签名声明一个闭包。这样做可以将JSON转换为符合ResponseObjectSerializable协议的相应类。

17到19行 - 这里我们称之为&#34;响应()&#34; Alamofire.Request类中的方法(我认为?)传入先前定义的序列化器闭包。我们传入的是实际的 completionHandler闭包,然后调用其他一些神秘的completionHandler方法。这个&#34;响应()&#34;的结果方法调用返回给客户端代码。

我觉得我理解到&#34; completionHandler&#34;闭包在第17行作为参数传递。但是后来我们调用了其他一些&#34; completionHandler&#34; - 它在哪里定义?还是自称?

另外,当第7行创建的序列化程序看起来超出了第7行的范围时,我们如何引用它?

1 个答案:

答案 0 :(得分:3)

如果您不理解,只需获取原始代码......

  1 @objc public protocol ResponseObjectSerializable {
  2   init(response: NSHTTPURLResponse, representation: AnyObject)
  3 }
  4
  5 extension Alamofire.Request {
  6   public func responseObject<T: ResponseObjectSerializable>(completionHandler: (NSURLRequest, NSHTTPURLResponse?, T?, NSError?) -> Void) -> Self {
  7     let serializer: Serializer = { (request, response, data) in
  8       let JSONSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
  9       let (JSON: AnyObject?, serializationError) = JSONSerializer(request, response, data)
 10       if response != nil && JSON != nil {
 11         return (T(response: response!, representation: JSON!), nil)
 12       } else {
 13         return (nil, serializationError)
 14       }
 15     }
 16
 17     return response(serializer: serializer, completionHandler: { (request, response, object, error) in
 18       completionHandler(request, response, object as? T, error)
 19     })
 20   }
 21 }

...删除不相关的部分或像这样折叠它们......

  5 extension Alamofire.Request {
  6   public func responseObject<T: ResponseObjectSerializable>(completionHandler: (NSURLRequest, NSHTTPURLResponse?, T?, NSError?) -> Void) -> Self {
  7     let serializer: Serializer = { ... }
 16
 17     return response(serializer: serializer, completionHandler: {
 18       ...
 19     })
 20   }
 21 }

...当你知道它正在做什么时,逐一展开折叠的部分。

那么,那里有什么......

第6行的

completionHandler - public func responseObject<...函数的第一个参数。它是一个闭包,你可以传递或使用它(执行它)。以下是Apple文档引用:

  

闭包是可以传递的自包含功能块   在您的代码中使用。 Swift中的闭包类似于块   在C和Objective-C以及其他编程语言中的lambda。

如果你想使用闭包(执行它),你可以使用它作为这样的函数:

completionHandler(pass arguments, to, this closure, here)

如果您想传递它,只需使用参数名称completionHandler

Closures & Swift docs

第17行的

completionHandler - func response的第二个参数。在这里,我们通过第18行定义的功能(现在已折叠)传递闭包。此闭包可以在response函数内使用,并通过参数名completionHandler引用。但只有response函数内部才有这个功能。那么,让我们扩展它......

  5 extension Alamofire.Request {
  6   public func responseObject<T: ResponseObjectSerializable>(completionHandler: (NSURLRequest, NSHTTPURLResponse?, T?, NSError?) -> Void) -> Self {
  7     let serializer: Serializer = { ... }
 16
 17     return response(serializer: serializer, completionHandler: {
 18       completionHandler(request, response, object as? T, error)
 19     })
 20   }
 21 }

现在发生了什么......

  1. response函数内部,我们传递的第17-19行的闭包可以传递或使用。

  2. 当它发生时,执行此闭包的主体(第18行)。

  3. 闭包体使用另一个闭包,它作为参数传递给函数responseObject

  4. 使其更短......当response执行completionHandler闭包(第17-19行)时,此闭包执行另一个闭包(第18行),该闭包作为参数传递给函数{{ 1}}(第6行)。

    希望它能说清楚。这并不难,只是在分析代码时学习如何跳过代码的某些部分(在你的脑海中崩溃)。