【问题标题】:Understanding Alamofire's Response Object Serialization use of Closures了解 Alamofire 的响应对象序列化使用闭包
【发布时间】:2015-06-23 06:39:27
【问题描述】:

我试图理解以下来自Ray Wenderlich tutorial 的示例。我的主要困惑不是 what(以方便的方式将 JSON 数据反序列化到您自己的对象中),而是 如何 它正在这样做。我要做的是按照我的理解解释代码 sn-p 但我的困惑源于 completionHandler 闭包和它的类型定义。在我初步了解代码的作用之后,我会强调这一点。

首先是带有行号的sn-p:

  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?) -&gt; Void 签名的“completionHandler”闭包。然后它返回它自己的类 -&gt; self 的一个实例。

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

第 17 到 19 行 - 这里我们调用 Alamofire.Request 类中的“response()”方法(我认为?)传入之前定义的序列化程序闭包。我们还传入一个 actual completionHandler 闭包,然后调用其他一些神秘的 completionHandler 方法。这个“response()”方法调用的结果返回给客户端代码。

我觉得我理解到了在第 17 行将“completionHandler”闭包作为参数传递的程度。但是我们调用了其他一些“completionHandler”——它在哪里定义?还是它在呼唤自己?

另外,第 17 行的序列化程序在第 7 行创建时看似超出范围,我们是如何引用它的?

【问题讨论】:

  • 不,第 18 行调用 completionHandler 闭包作为参数传递给第 6 行的 responseObject&lt;...。第 17-19 行返回 response 并带有 intermediate 闭包在第 6 行调用 completionHandler 闭包并传递与接收到的相同的参数,但有一个异常 - 它尝试将 object 转换为 T,然后将其传递给 completionHandler(第 6 行)。
  • 这样就更清楚了,谢谢。随意添加它作为答案,我会接受它。
  • 做到了,稍微增强了一点,所以,它可以被视为一个答案:-)

标签: swift serialization alamofire


【解决方案1】:

如果你不明白,就拿你原来的代码吧……

  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&lt;... 函数的第一个参数。这是一个闭包,您可以传递它或使用它(执行它)。这是 Apple 文档的引用:

闭包是可以传递的独立功能块 周围并在您的代码中使用。 Swift 中的闭包类似于块 在 C 和 Objective-C 以及其他编程语言中的 lambdas 中。

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

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行) )。

希望它说清楚。没那么难,只要学习如何在分析代码时跳过某些部分(在脑海中折叠)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-20
    • 1970-01-01
    • 2017-03-08
    • 1970-01-01
    • 2017-11-03
    相关资源
    最近更新 更多