读代码 Me

文章目录
  1. 1. 为什么看
  2. 2. 他是做什么的
  3. 3. 使用他以后的效果
  4. 4. 源码
    1. 4.1. 先看接口
    2. 4.2. 看代码实现

为什么看

抽空晚上睡不着看 awesome-ios 提供的优秀代码库
[Me](https://github.com/pascalbros/Me 源码

他是做什么的

Me 是解决嵌套异步问题的一个轻量级库——就一个文件

使用他以后的效果

before

1
2
3
4
5
6
7
8
9
10
11
12
MyAPI.login {
//Do your stuff and then request posts...
MyAPI.posts {
//Do your stuff and then request comments...
MyAPI.comments {
//Do your stuff and then request likes...
MyAPI.likes {
//We are done here
}
}
}
}

after

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Me.start { (me) in
MyAPI.login {
//Do your stuff and then request posts...
me.runNext()
}
}.next { (caller, me) in
MyAPI.posts {
//Do your stuff and then request comments...
me.runNext()
}
}.next { (caller, me) in
MyAPI.comments {
//Do your stuff and then request likes...
me.runNext()
}
}.next { (caller, me) in
MyAPI.likes {
//We are done here
me.end()
}
}.run()

看效果:

  1. Me 把异步嵌套代码–> 链式代码(想想他是怎么做的?)
  2. Me 是链条型的,start,next,next(name:),jump(toName:),end
    1. 他是如何做异步通知的?
    2. 如何开始,如何结束?
    3. 支持实现多链条并发执行吗?
  3. 从提供的接口上可以看出
    1. Me开启结束要由用户控制
    2. 节点驱动需要用户触发
    3. 支持指定节点跳转

ok 使用demo&基本特性分析完了,接下来看源码


源码

先看接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public typealias MeInitClosure = ((_ current: Me) -> ())
public typealias MeClosure = ((_ previous: Me?, _ current: Me) -> ())

public var first: Me { get }
public var index: UInt { get }
internal var name: String { get }
public var parameters: [String : Any]

// 链式节点函数,static 是起点
public static func start(name: String = "", this: @escaping MeInitClosure) -> Me
public static func run(this: @escaping MeClosure) -> Me
public func next(name: String = "", next: @escaping MeClosure) -> Me

public func run()
public func end()
public func runNext(queue: DispatchQueue)
public func runNext()
public func runNextOnMain()
public func jump(toIndex jump: UInt = 0, queue: DispatchQueue)
public func jump(toIndex jump: UInt = 0)
public func jumpOnMain(toIndex jump: UInt = 0)
public func jump(toName jump: String, queue: DispatchQueue)
public func jump(toName jump: String)
public func jumpOnMain(toName jump: String)
  1. 提供 Me 节点 index,name,代码库内部维护
  2. 只提供其实节点 first
  3. 提供线程队列调度接口
  4. parameters 是干什么的?像是 [name: MeClouse] 字典,每个 me 节点都有一个clouse

看代码实现

  1. 核心代码,这个地方封装了 GCD
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public func runNext(queue: DispatchQueue) {
if let next = self.next {
//self.nextObj!.parameters = self.parameters //enable to pass parameters to the next object
queue.async {
next(self, self.nextObj!)
}
}
}

public func jump(toIndex jump: UInt = 0, queue: DispatchQueue) {
if let to = me(at: jump) {
to.this(self, to)
}
}

有个问题是:jump 的queue 没有用……(这个库的使用价值不大)只有 runNext 相关方法可以调度线程
parameters: 是 me 节点保存数据,用于用户自己传递数据使用

  1. 内部数据结构使用的是链表
1
2
private var nextObj: Me?
private var _first: Me?