ReactiveCocoa的那些干货~

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/block_xh/article/details/51063661

 

 


前言:

笔者接触RAC框架已经一年多的时间了,从2014年底开始接触到RAC,当时总觉得怪怪的,或者是因为经验不足吧,在学习以及使用过程中总是会闹点什么笑话。而说到RAC框架,不得不说起MVVM设计模式,本文中的内容主要是对RAC基于UI方面的封装的个人使用过程中的一些心得体会,好了,闲话不多说,开始干货吧~!

 

 

ReactiveCocoa简介

首先,关于RAC,相信很多对于iOS开发有过经验的开发者应该是不陌生的,ReactiveCocoa(简称为RAC,是由Github开源的一个应用于iOSOS开发的新框架。RAC框架通过对传统的KVOKVCDelegateBlockNSNotification等一系列iOS/OS中关键性的设计模式做出了一个统一,形成了自己独特的响应式编程思维,通过Hot SignalCool Signal 的抽象性概念,以类block的方法简化了我们的代码量。

 

 

ReactiveCocoa构建介绍

         RAC的基本构建如下:

                      

                       Core文件夹中包含了对OC里我们常用的类别的Category的拓展,以及RAC最重要也是最为关键的几个类:RACArraySequence、RACBacktrace、RACBehaviorSubject、RACBlockTrampoline、RACChannel、RACCommand、RACCompoundDisposable、RACDelegateProxy、RACDisposable、RACDynamicSequence、RACScheduler、RACReturnSignal、RACKVOProxy、RACStream、RACSubject、RACTuple、RACSignal等一系列以RAC为开头的类,大家如果有兴趣可以自己去下载一份RAC的源码,看看这些关键类的实现。

 

                       No-arc文件夹这是对于Runtime的一个方法封装,关于Runtime,笔者这里就不多说,相信大家哪怕没有正统看过或者用过也应该是听过Runtime的大名,RAC这里的Runtime笔者的理解是对这个Category的一个封装,该Category则是RAC方法的信号封装,有兴趣的读者可以去看看。

 

                       SupportFiles文件夹中存放的是跟cocoapods相关的文件,由于笔者使用的是cocoapods进行RAC框架的集成,而非下载源码后过通过自己的过滤来的源码库,关于cocoapods,这里不多做介绍。

 

                       UI文件夹中存放的是RAC关于UIKit中常用的控件的Category拓展,这个拓展是基于RAC对传统模式下的封装进行的,本文中,笔者将对这部分的干货进行个人使用过程中的心得进行介绍。

 

 

ReactiveCocoa – UI Category介绍

                 首先,我们先来看下RAC关于UIKit中到底做了些什么?如图:

以上就是RAC框架中对UIKit的一些拓展,那么,这些拓展是干什么用的呢?以UIAlertView为例。UIAlertView相信大家都不陌生,这个是系统下iOS的默认弹框,在项目中我们经常会去使用到它,常规的使用如下:

 

    UIAlertView *alertView = [[UIAlertViewalloc] initWithTitle:@"title"message:@"message"delegate:selfcancelButtonTitle:@"cancelButtonTitle"otherButtonTitles:@"otherButtonTitles",nil];

    alertView.tag = 888;

[alertView show];

 

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {

   

    if (alertView.tag ==888 && buttonIndex == 0) {

        //cancel的处理。。。。。

    }

}

 

那么RAC中对UIAlertView做了怎么样的封装呢?让我们来看看它的Category吧!

 

 

RAC通过 Runtime 添加了一个RACDelegateProxy 属性成员变量,关于这个RAC类,笔者这里简单做下说明:RACDelegateProxy是RAC框架中对传统Delegate进行封装的一个类,它通过Runtime对Delegate进行拦截,获取到注册方法中的委托回调,同时把这个拦截到的委托回调以信号的形式(Signal)的形式逐级传递。

 

RAC中通过注册了UIAlertViewDelegate 对 willDismissWithButtonIndex和 clickedButtonAtIndex 的委托进行了拦截,也就是说,传统使用UIAlertView过程中,我们获取到UIAlertView对象的点击事件是由UIAlertViewDelegate进行委托回调的,而RAC中,我们则可以这么做:

 

UIAlertView *alertView = [[UIAlertViewalloc] initWithTitle:@"title"message:@"message"delegate:selfcancelButtonTitle:@"cancelButtonTitle"otherButtonTitles:@"otherButtonTitles",nil];

    [alertView show];

   

    [[[alertView rac_buttonClickedSignal]deliverOn:[RACSchedulermainThreadScheduler]] subscribeNext:^(id x) {

        //UIAlertViewDelegate的委托

}];

 

是的,RAC中,我们可以通过-rac_buttonClickedSignal这个方法获取到委托回调的事件了,是不是方便许多了?并且在代码量上也减少了许多,这样的好处是可以防止过多的委托方法堆积在一个类中,在代码的规范、维护和更新中会起到很好的作用。

 

好了,现在我们进一步对RAC的UIKit进行封装,从上面的内容中,我们大体的知道了RAC关于UIAlertView做的事情,那么接下去,我们就要对UIAlertView关于RAC进行第二次的封装,以下为笔者对UIAlertView和RAC下的一个进一步的封装:

 

         

     我们创建一个UIAlertView的Category拓展,拓展中,我们需要实现以下代码:

     + (RACSignal *)rac_showAlertViewWithTitle:(NSString *)title message:(NSString *)messagedelegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... {

   

    va_list args;

    va_start(args, otherButtonTitles);

   

    UIAlertView *alertView = [[UIAlertViewalloc] initWithTitle:titlemessage:message delegate:delegatecancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitles,nil];

    NSString *others = va_arg(args,NSString *);

   

    while (others) {

        [alertView addButtonWithTitle:others];

        others = va_arg(args, NSString *);

    }

    va_end(args);

   

    [alertView show];

    return [RACSignalcreateSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

       

        [[[alertView rac_buttonClickedSignal]deliverOn:[RACSchedulermainThreadScheduler]] subscribeNext:^(id x) {

            [subscriber sendNext:x];

            [subscriber sendCompleted];

        }];

        return nil;

    }];

}

 

关于这个二次方法的封装,思路是这样的:关于UIAlertView的常规使用和关于RAC对UIAlertViewDelegate的Signal思想进行结合,也就是以上代码中的内容,改方法中模范UIAlertView方法的传值方式,使用va_list进行字符串的遍历,通过- addButtonWithTitle方法对遍历到的字符串进行动态添加,也就是动态添加UIAlertView的button数目,关于va_list,不清楚的童鞋可以自行百度下,或者使用过FMDB这个库的童鞋可以去FMDB的源码中看看,FMDB的作者在SQL语句的拆分上就是使用了它对方法中的字符串进行处理的,笔者这里就不多做介绍了。然后使用RACSignal的- createSignal方法创建一个管道,把UIAlertView关于RAC的Delegate中截取的委托信号传递到最外层的出口处,这样我们就能在外层去获取到信号了。关于RACSignal,这个是RAC中对Signal这个概念的一个总结,涉及到热信号冷信号的概念,笔者在以后的博客中会陆续的介绍它。回到我们原来的话题,那么如何使用它呢?如下:

 

 

[[UIAlertView rac_showAlertViewWithTitle:@"test" message:@"这是一个测试的"delegate:selfcancelButtonTitle:@"0"otherButtonTitles:@"1",@"2",@"3",@"4"]subscribeNext:^(NSNumber *x) {

           NSLog(@"x: %@", x);

       }];

 

是不是觉得代码量大大的减少了呢?并且使用的时候感觉更加方法了?没错,这就是RAC要实现的效果,不禁是要减少代码量,防止大量代码在同一个类中堆积,同时也要让我们的代码更加整洁,维护更加简便,最重要的是要降低代码的耦合性,关于耦合性,笔者在自己的项目或者框架中是使用的MVVM模式的,关于这个,今后的博客中将陆续介绍。

 

 

 

总结:

         关于RAC,笔者有太多话想说,在今后的博客中也将陆续为大家提供一些干货和个人使用以及学习RAC过程中的一些小心得和体会,同时也欢迎各个RAC大神和童鞋们一起学习,如果有问题也请大家不吝赐教~!

           关于RAC,比如唐巧等知名的技术博主都有相应的博客,小伙伴们如果有兴趣可以自行去看看哦!笔者这里给大家提供点大神们关于RAC的博客的传送门:

 

http://www.raywenderlich.com/62699/reactivecocoa-tutorial-pt1
http://www.raywenderlich.com/62796/reactivecocoa-tutorial-pt2
http://www.raywenderlich.com/74106/mvvm-tutorial-with-reactivecocoa-part-1
http://www.raywenderlich.com/74131/mvvm-tutorial-with-reactivecocoa-part-2

http://tech.meituan.com/tag/ReactiveCocoa

http://limboy.me/

 

http://blog.leichunfeng.com/blog/2015/12/25/reactivecocoa-v2-dot-5-yuan-ma-jie-xi-zhi-jia-gou-zong-lan/

 

 


展开阅读全文

没有更多推荐了,返回首页