本来是一直在swift中使用到的库Bolts-Swift。
由于换项目的原因,发现新OC项目中没有使用到这个库,而我写的实现中需要这个库才显得更简介(当然其它方式也能行,但是总感觉不爽呐),就找到了OC版本Bolts-ObjC。
但是又不能为了几行代码就去安装这个库吧,所以趁现在解读下源代码,自己写个简化版本的。
下面是GitHub的地址:
OC版本:Bolts-ObjC
swift版本:Bolts-Swift
这篇文章写的是OC版本的,下篇会写上swift版本
首先
来看下我们一般会使用到的方法吧,从这里入手。
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"开始");
[[self getStringAsync:@"111"] continueWithBlock:^id _Nullable(BFTask * _Nonnull t) {
NSLog(@"%@", t.result);
return t.result;
}];
[[self getStringAsync:@"222"] continueWithSuccessBlock:^id _Nullable(BFTask * _Nonnull t) {
NSLog(@"%@", t.result);
return t.result;
}];
NSLog(@"结束");
}
//返回Task对象
- (BFTask *)getStringAsync: (NSString *)str{
//创建
BFTaskCompletionSource *successful = [BFTaskCompletionSource taskCompletionSource];
dispatch_async(dispatch_get_main_queue(), ^{
[successful setResult:str];
});
return successful.task;
}
打印结果
2018-04-16 10:38:32.974577+0800 rqrr[2607:83284] 开始
2018-04-16 10:38:32.975714+0800 rqrr[2607:83284] 结束
2018-04-16 10:38:32.982849+0800 rqrr[2607:83284] 111
2018-04-16 10:38:32.983826+0800 rqrr[2607:83284] 222
大概意思就是,dispatch_async异步线程处理完成,将结果回掉。
首先创建了一个BFTaskCompletionSource类使用了类方法[BFTaskCompletionSource taskCompletionSource];
看下源代码中实现
在这个BFTaskCompletionSource类中其中一部分,其他先不看。

BFTask对象 ,还一个构造方法,并且都使用了__covariant - 协变性可以将子类强转到父类。
而构造方法中写的也很简单,如下:

BFTask大多都是类方法、构造方法,放一边,先看我们经常使用的。
在viewdidLoad中这句代码。
[[self getStringAsync:@"111"] continueWithBlock:^id _Nullable(BFTask * _Nonnull t) {
NSLog(@"%@", t.result);
return t.result;
}];
将调用返回的BFTask对象的continueWithBlock方法。好,我们来看看这里。

调用了另一个对象。并且传入了[BFExecutor defaultExecutor]
呢么BFExecutor是什么呢?
大概意思就是返回一个线程安全的单例对象。

- (BFTask *)continueWithExecutor:(BFExecutor *)executor block:(BFContinuationBlock)block cancellationToken:(nullable BFCancellationToken *)cancellationToken { BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource]
最主要的方法,很长没问先从下面开始看

在找里 @synchronized(self.lock)相当于线程锁的作用。很多地方都用到,意思是这些操作,执行完成前,其它地方都锁住。
紧接着是后面self.comleted初始化是NO,所以执行到这里,会将你的block回掉方法。
都储存在self.callbocks并且运用之前的单例对象,拷贝一个含有block的对象。
以下写法,将会执行两次上述方法然后,在self.callbocks中就有两个block。
[[[self getStringAsync:@"111"] continueWithBlock:^id _Nullable(BFTask * _Nonnull t) {
NSLog(@"第一个%@", t.result);
return t.result;
}] continueWithBlock:^id _Nullable(BFTask * _Nonnull t) {
NSLog(@"第二个%@", t.result);
return t.result;
}];
呢么回掉方法都存储在了数组里,什么时候调用的呢?
看下面代码,全部复制成功后,在你执行的异步方法中。调用的[successful setResult:str];中
//返回Task对象
- (BFTask *)getStringAsync: (NSString *)str{
//创建
BFTaskCompletionSource *successful = [BFTaskCompletionSource taskCompletionSource];
dispatch_async(dispatch_get_main_queue(), ^{
[successful setResult:str];
});
return successful.task;
}
在这里调用了trySetResult方法

在这也有self.lock锁,这里的self.completed之前说过是NO 所以,会走下面的判断,将result复制,执行[self runContinuations]方法

最后就是 runContrnuations方法是执行了什么呢?
在这里看到,lock、 broadcast、unlock 。锁定->释放所有线程锁->解锁。然后循环执行block方法。最后将block数组清空。
