Moya 阅读笔记

Moya 阅读笔记最近两天在阅读 Moya,一个在基于 Alamofire 的对网络请求进行封装的框架。下面是我的阅读笔记。

大家好,欢迎来到IT知识分享网。

最近两天在阅读 Moya,一个在基于 Alamofire 的对网络请求进行封装的框架。下面是我的阅读笔记。

范围表达式 RangeExpression

下面是过滤网络状态(statusCodes)的filter方法:

func filter<R: RangeExpression>(statusCodes: R) throws -> Response where R.Bound == Int { guard statusCodes.contains(statusCode) else { throw MoyaError.statusCode(self) } return self }

在表示可以接收的 statusCodes 的范围时,使用了 RangeExpression。

Swift 中表示范围时有多种类型:

一、范围(Range):

  • 元素类型要求满足 Comparable半开范围(Range):比如 0..<10;
  • 闭合范围(ClosedRange):比如 0…10;

二、可数范围,和 Range 相比,它的元素类型需要遵守 Strideable 协议 (以整数为步长):

  • 可数半开范围(CountableRange):。 比如 0..<10。
  • 可数闭合范围(CountableClosedRange):。 比如 0…10。

三、部分范围 (partial range):指的是将 … 或 ..< 作为前置或者后置运算符来使用时所构造的范围:

  • … 作为后置,比如 Character(“a”)…
  • … 作为前置,比如 …Character(“z”)
  • ..< 作为后置,比如 ..<10
  • ..< 作为前置,比如 10..<

上面的八种类型都符合 RangeExpression 协议。

标签语句——提前结束循环语句和条件语句

在 Moya 中 Response 类中,有一段代码使用了标签语句:

let jsonData: Data keyPathCheck: if let keyPath = keyPath { guard let jsonObject = (try mapJSON(failsOnEmptyData: failsOnEmptyData) as? NSDictionary)?.value(forKeyPath: keyPath) else { if failsOnEmptyData { throw MoyaError.jsonMapping(self) } else { jsonData = data break keyPathCheck } } if let data = try serializeToData(jsonObject) { jsonData = data } else { // 省略部分代码 } } else { jsonData = data } // 省略下面针对 jsonData 的操作

在循环中,经常会用到 break 语句,来提前结束循环。

其实,在 Swift 的循环语句和条件语句中,都可以使用 break + 标签语句来提前结束它们的执行。上面的代码是一个很好的例子,在 if 条件中,需要提前结束 if 语句,继续执行下面的内容时,就用到了 break keyPathCheck。如果此处不使用 break + 标签的方式,后继针对 jsonData 的操作将会出现重复的代码。

使用 break 可以简化代码,同时势必会增加阅读代码的难度。

为了避免重复代码的出现,也可以通过其他方式:

  • 将代码进行抽离,新增一个实例方法;
  • 直接在方法内部再定义一个方法或者闭包,处理相似的逻辑。

给枚举(enum)加个“父类”

Moya 的核心类 MoyaProvider 的定义如下:

open class MoyaProvider<Target: TargetType>: MoyaProviderType { }

在初始化 MoyaProvider 时,要明确泛型 Target 的具体类型。实现 TargetType 协议使用的是枚举类型(enum)。假如我们需要把网络请求分成多个模块,放到不同的枚举中,那应该将 Target 指定为什么呢?

如果使用类(class)来实现 TargetType 协议,我们可以创建一个父类,指定为父类类型。但是枚举(enum)类型无法继承。

Moya 的解决方案是 MultiTarget:

public enum MultiTarget: TargetType { /// The embedded `TargetType`. case target(TargetType) /// Initializes a `MultiTarget`. public init(_ target: TargetType) { self = MultiTarget.target(target) } // 省略部分代码 }

MultiTarget 的设计非常简单,仅仅是保存了初始化传入的 target: TargetType,并用 target 实现 TargetType 协议。它达到了类的多态(我没办法说清楚 MultiTarget 的设计模式):

  1. MultiTarget 的具体表现由传入的 target 来负责,类似于子类重写父类的方法;
  2. MultiTarget 类似于“父类”,对外提供了统一的接口。

如果表达得不准确,欢迎指正,谢谢。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/56304.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信