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

Understanding Alamofire's Response Object Serialization use of Closures

我正在尝试理解取自此 Ray Wenderlich tutorial 的以下示例。我的主要困惑不在于 what(以一种方便的方式将 JSON 数据反序列化到您自己的对象中)它在做什么,而是 how它正在做。我要做的是按我的理解解释代码片段,但我的困惑源于 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 行 - 在这里我们声明了一个通用函数 (responseObject),它接受一个带有 (NSURLRequest, NSHTTPURLResponse?, T?, NSError?) -> Void 签名的 "completionHandler" 闭包。然后它 returns 它自己的一个实例 class -> self.

第 7 到 15 行 - 这里我们使用 Serializer 签名声明一个闭包。这确实将 JSON 转换为符合 ResponseObjectSerializable 协议的适当 class 的实际工作。

第 17 到 19 行 - 这里我们在 Alamofire.Request class(我想?)中调用 "response()" 方法,传入先前定义的序列化器闭包。我们还传入的是一个 actual completionHandler 闭包,然后调用其他一些神秘的 completionHandler 方法。此 "response()" 方法调用的结果返回给客户端代码。

我觉得我理解到 "completionHandler" 闭包在第 17 行作为参数传递的地步。但是然后我们调用其他一些 "completionHandler" - 它在哪里定义?还是它在调用自己?

此外,当第 7 行的序列化器看似超出范围创建时,我们如何引用第 17 行的序列化程序?

不懂就拿你的原码...

  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 }

...当你知道它在做什么时,将折叠的部分一个接一个地展开。

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

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

Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages.

如果你确实想使用闭包(执行它),你可以像这样将它用作函数:

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

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

Closures & Swift docs.

completionHandler 第 17 行 - 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

为了让它更短......当response执行completionHandler闭包(第17-19行)时,这个闭包执行另一个闭包(第18行),它作为参数传递给函数responseObject...(第 6 行)。

希望它能说清楚。没那么难,只要学会在分析代码的时候跳过部分代码就可以了(脑子里折叠起来)。