编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

Moya 阅读笔记(12篇阅读笔记)

wxchong 2024-09-07 01:25:42 开源技术 10 ℃ 0 评论

最近两天在阅读 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 类似于“父类”,对外提供了统一的接口。

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

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表