object-c

第一天打开头条号好激动。以前微博觉得互动太少,转头试试。

首先了解什么是链式编程:链式编程主要是通过点“.”连接不同的函数调用。(我不知道这个定义对不对,但是我感觉这个定义很奇怪,我就随便理解一下吧)。但是由于oc语法的特点,通过点操作连接不同的函数调用,尤其是向调用函数传入参数,并不是那么容易。首先,让我们来看看几种编程思想(链式编程、响应式编程、函数式编程)——phxiang的博客——CSDN的博客。

Oc语言链(函数式)编程以Masonry,PromiseKit为代表。它们的共同点是1。点连接没有参数方法或属性。2.返回的对象是相同的实例对象或可以返回实例对象的块方法。

object-c

图1

上图是砖石的一个应用。top、left等方法都是返回MASConstraint实例对象而不传入参数的方法。

图2

方法equalTo是一个块,返回值为MASConstraint实例对象,这样当我们传入参数时,就会触发该块的执行,返回MASConstraint实例对象,这样链结构就可以延续。

图3

了解了如何在oc结构上实现链式结构之后,我们来分析一下如何使用promiseKit实现链式结构:

图4

关于promiseKit的内部实现原理,请参考promisekit的原文。明确了PromiseKit的原理后,个人感觉每次要向下传递链结构的值,都需要传入一个新的Anypromise对象,用block块来传递。感觉代码不是很“对称”。PromiseKit只是实现Promise设计模式的一种方式,并不能给我们的app带来任何“看得见”的好处,只是为了满足我们对“代码美学”的追求。为了解决这一美学问题,我们试图通过使用承诺的结构来改进代码。如下所示,封装了一个MyPromise类,并使用第一个类方法创建了一个MyPromise对象。要执行的代码块放在第一个方法的参数块中,如下所示。after()使用GCD_After来模拟异步的耗时操作。

图5

在then实例方法中,所有连接的then方法中的块将被收集并放置在一个数组中,以强引用该块来防止它被释放,因为直到收集了所有的then.block,才会触发该块的执行。

图6

当所有的then.block、first.block和catcher’s block连接后,start方法触发first.block,获得值时存储的then.block数组触发相应的块,值互相传递。

当第一个块的块得到需要的值且没有异常数据时,通过执行excuteThenBlock的值,将第一个块的值传递给下一个要触发执行的块,递归执行剩余的then.block,并相应地传递值,执行完成后将立即移除并释放数组中的块:

Mypromise的演示地址;

如果有什么意见或建议,可以留言交流。如果我有什么错误或不足,希望指出改正,互相交流。PromiseKit的功能远不止解决异步嵌套问题,它还有类似GCD中dispatch_group的线程依赖的功能。这里的Mypromise只是展示函数链编程思想的演示,有兴趣的可以作为从业者学习。

附上源代码:

===============================================================

#导入& ltfoundation/foundation . h & gt;NS _ ASSUME _ NONNULL _ BEGIN @ class my promise;typedefvoid(^catcherrblock)(nserror*err);typedefvoid(^paslock)(idobj);typedefvoid(^adapter)(iddata,paslockpass);typedefvoid(^firlock)(paslockpass);typedefmypromise*(^__firlock)(firlockfirst);@ interfaceMyPromise:ns object/* *首先用First block */+(MyPromise *)First:(firlock)block创建my promise对象;@property (nonatomic,class,copy,readonly)_ _ Firlock first;/** then方法继续link */@ property (nonatomic,copy,readonly)my promise *(then)(adapter adapter);/* *接收*/@ property (nonatomic,copy,readonly)my promise *(catcher Error)(catcher lock RR block)时出错;/* *开始执行*/-(void)开始;@ endNS _ ASSUME _ NONNULL _ END = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = # import ” my promise . h ” @ interface my promise()@ property(nonatomic,strong)Firlock first block;@property (nonatomic,strong)CatchErrBlock error block;@property (nonatomic,strong)NutableArray * adapter blocks;@ end @ implementation my promise-(instance type)init { if(self = =[superinit]){ self . adapter blocks =[[NutableArrayalloc]init];}回归自我;}+(my promise *)first:(Firlock)block { my promise * promise =[[MyPromisealloc]init];promise.firstBlock = blockreturnpromise}+(_ _ firlock)first { return^(firlockfirst){ my promise * promise =[[mypromisealloc]init];promise.firstBlock = firstreturnpromise};}-(mypromise*_nonnull(^)(adapter_nonnull))then { _ _ weak type of(self)weak self = self;return^(adapteradapter){ if(adapter)[weak self . adapterblocksaddobject:adapter];returnweakSelf};}-(mypromise*_nonnull(^)(catcherrblock_nonnull))catcherror { _ _ weak type of(self)weak self = self;return^(catcherrblockerrblock){ if(err block)weak self . error block = err block;returnweakSelf};}-(void)start { Firlock block = self . first block;Paslockclass = (id data) {/* *为了保持MyPromise生命周期在异步环境下延长,这里使用了强引用*/if([dataiskindofclass:[nserrorclass]]){[self excute errorlock:data];} else {[self execute tenblock:data];} };阻挡(通过);}-(void)execute tenblock:(id)data { Adapter Adapter = self . Adapter blocks . first object;Paslockclass = (id newdata) {/* *为了保持MyPromise生命周期在异步环境下延长,这里使用了强引用*/if([newdataiskindofclass:[nserrorclass]]){[self excute error lock:new data];} else {[selfexcuteThenBlock:new data];} };if(adapter){[self . adapterblocksremoveobject:adapter];适配器(数据,传递);} }-(void)excuteErrorBlock:(NSError *)error { CatchErrBlock err block = self . error block;if(err block){ err block(error);}}@end

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

发表回复

登录后才能评论