首页 > 其他 > 详细

ReactiveCocoa 学习笔记

时间:2015-12-31 02:13:28      阅读:258      评论:0      收藏:0      [点我收藏+]

#pragma mark - 各种方便的block封装? ReactiveCocoa

/*

?概述:

?可以把信号想象成水龙头,只不过里面不是水,而是玻璃球(value),直径跟水管的内径一样,这样就能保证玻璃球是依次排列,不会出现并排的情况(数据都是线性处理的,不会出现并发情况)。水龙头的开关默认是关的,除非有了接收方(subscriber),才会打开。这样只要有新的玻璃球进来,就会自动传送给接收方。可以在水龙头上加一个过滤嘴(filter),不符合的不让通过,也可以加一个改动装置,把球改变成符合自己的需求(map)。也可以把多个水龙头合并成一个新的水龙头(combineLatest:reduce:),这样只要其中的一个水龙头有玻璃球出来,这个新合并的水龙头就会得到这个球。

?具体使用:

?当一个signal被一个subscriber subscribe后,这个subscriber何时会被移除?答案是当subscribersendCompletesendError时,或者手动调用[disposable dispose]

?

?subscriberdispose后,所有该subscriber相关的工作都会被停止或取消,如http请求,资源也会被释放。

?

?Signal events是线性的,不会出现并发的情况,除非显示地指定Scheduler。所以-subscribeNext:error:completed:里的block不需要锁定或者synchronized等操作,其他的events会依次排队,直到block处理完成。

?

?Errors有优先权,如果有多个signals被同时监听,只要其中一个signal sendError,那么error就会立刻被传送给subscriber,并导致signals终止执行。相当于Exception

?

?生成Signal时,最好指定Name, -setNameWithFormat: 方便调试。

?

?block代码中不要阻塞。

?

?*/

-(void)reactiveCocoaDemoAction{

//? ? __weak typeof(self) wSelf = self;

//? ? 因为RAC是基于KVO的,而NSMutableArray并不会在调用addObjectremoveObject时发送通知

? ? //------------------------------------通知监听----------------------------------------

? ? [[[NSNotificationCenterdefaultCenter] rac_addObserverForName:@"log_out"object:nil] subscribeNext:^(id x) {

? ? ? ? //? ? ? ? NSNotification* notification = (NSNotification*)x;

? ? ? ? //? ? ? ? int unreadClubMsgCount = 0;

? ? ? ? //? ? ? ? if (notification.object) {

? ? ? ? //? ? ? ? ? ? unreadClubMsgCount = [notification.object intValue];

? ? ? ? //? ? ? ? }

? ? ? ? //退出登录的通知。---"log_out"是自定义的

? ? }];

?? ?

? ? //退出登录后执行。。。。上面的通知方法就可以触发了。

? ? [[NSNotificationCenterdefaultCenter]postNotificationName:@"log_out"object:nil];

?? ?

? ? //------------------------------------UITextField输入限制-----------------------------

? ? UITextField *textField;//自己写初始化

? ? [textField.rac_textSignal subscribeNext:^(NSString* text) {

? ? ? ? if(text.length > 12){

? ? ? ? ? ? textField.text = [text substringToIndex:12];

? ? ? ? }

? ? }];

? ? //------------------------------------UIAlertView,UIActionSheet点击方法-----------------------------

? ? UIAlertView *alertView;//自己写初始化

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

? ? ? ? if ([x integerValue] == 1) {//alert的按钮

?? ? ? ? ? ?

? ? ? ? }

? ? }];

? ? [alertView show];

? ? UIActionSheet* actionSheet ;

? ? [[actionSheet rac_buttonClickedSignal] subscribeNext:^(id x) {

? ? ? ? if ([x integerValue] == 1) {//actionSheet的按钮

?? ? ? ? ? ?

? ? ? ? }

? ? }];

//? ? [actionSheet showInView:self.view];

? ? //------------------------------------UIButton点击方法-----------------------------

? ? UIButton *button;//自己写初始化

? ? [[button rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {

?? ? ? ?

? ? }];

? ? //点击事件拦截。

? ? [[[button rac_signalForControlEvents:UIControlEventTouchUpInside]filter:^BOOL(UIButton *button) {

? ? ? ? if ([button.currentTitle isEqualToString:@"sd"]) {

? ? ? ? ? ? return YES;

? ? ? ? }else{

? ? ? ? ? ? return NO;

? ? ? ? }

? ? }]subscribeNext:^(id x) {

? ? ? ? NSLog(@"点击事件");

? ? }];

? ? //------------------------------------segmentedControl-----------------------------

? ? UISegmentedControl *segmentedControl;

? ? [[segmentedControl rac_signalForControlEvents:UIControlEventValueChanged] subscribeNext:^(id x) {

?? ? ? ?

?? ? ? ?

? ? }];

?? ?

? ? //---------------------------------------------RAC-------------------------------------------

? ? //---------------------------------------------RACObserver-------------------------------------------

//? ? RAC() 可以将Signal发出事件的值赋值给某个对象的某个属性,其参数为对象名和属性名

//? ? RACObserve() 参数为对象名和属性名,新建一个Signal并对对象的属性的值进行观察,当值变化时Signal会发出事件

? ? //某个属性一发生变化就执行。

? ? [RACObserve(self, count) subscribeNext:^(id x) {

? ? ? ? if ([x integerValue] == 0) {

?? ? ? ? ? ?

? ? ? ? }else if ([x integerValue] > 100){

?? ? ? ? ? ?

? ? ? ? }

? ? }];

? ?

? ? //返回Bool赋值给createEnabled

? ? RAC(self, createEnabled) = [RACSignal combineLatest:@[RACObserve(self, password),RACObserve(self, passwordConfirm)] reduce:^(NSString *pwd,NSString *pwdConfirm) {

? ? ? ? return @([pwd isEqualToString:pwdConfirm]);

? ? }];

?? ?

?? //--------------------------------------------map 用法 --------------------------------------------

? ? //map 改变返回的类型给结果管道。

? ? [[self.textField.rac_textSignal map:^id(NSString *text) {

? ? ? ? if ([text isEmptyString]) {

? ? ? ? ? ? return [UIColor whiteColor];

? ? ? ? }else{

? ? ? ? ? ? return [UIColor yellowColor];

? ? ? ? }

? ? }]subscribeNext:^(UIColor *color) {

? ? ? ? self.textField.backgroundColor = color;

? ? }];

?? ?

? ? [[[self.buttonrac_signalForControlEvents:UIControlEventTouchUpInside]map:^id(UIButton *button) {

? ? ? ? if ([button.currentTitle isEqualToString:@"按钮"]) {

? ? ? ? ? ? return [NSString stringWithFormat:@"按钮"];

? ? ? ? }else{

? ? ? ? ? ? return [NSString stringWithFormat:@"不是按钮"];

? ? ? ? }

? ? }]subscribeNext:^(NSString *resultString) {

? ? ? ? NSLog(@"%@",resultString);

? ? }];

? ? //--------------------------------------------filter 用法 --------------------------------------------

? ? //filter某个属性满足一定条件才执行。

? ? [[RACObserve(self, count) filter:^BOOL(id count) {//返回的是BOOL类型

? ? ? ? if ([count integerValue] == 5) {

? ? ? ? ? ? return YES;

? ? ? ? }else{

? ? ? ? ? ? return NO;

? ? ? ? }

? ? }]subscribeNext:^(id count) {//上面return YES 才走这里

? ? ? ? NSLog(@"数量为===%@",count);

? ? }];

?? ?

? ? //--------------------------------------------rac_command 用法 --------------------------------------------

? ? self.button.rac_command = [[RACCommandalloc]initWithSignalBlock:^RACSignal *(id input) {

? ? ? ? NSLog(@"按钮点击了。");

? ? ? ? //? ? ? ? [RACSignal return:@(6)];

? ? ? ? return [RACSignal empty];

? ? }];

?? ?

?? ?

? ? //----------------------------------------RACDisposable 用法 --------------------------------------------

?? ?

? ? RACSignal *backgrountColorSignal = [self.textField.rac_textSignal map:^id(NSString *text) {

? ? ? ? if ([text isEmptyString]) {

? ? ? ? ? ? return [UIColor whiteColor];

? ? ? ? }else{

? ? ? ? ? ? return [UIColor greenColor];

? ? ? ? }

? ? }];

? ? //subscrbeNext: 返回的类型是 RACDisposable

? ? RACDisposable *subscription = [backgrountColorSignal subscribeNext:^(UIColor *color) {

? ? ? ? self.textField.backgroundColor = color;

? ? }];

?? ?

? ? //----------------------------------------combineLaster 用法 --------------------------------------------

? ? //self.button.enables 属性 右边的signal sendNext 值绑定。

? ? RAC(self.button,enabled) = [RACSignal combineLatest:@[self.password,self.textField.rac_textSignal,RACObserve(self, passwordConfirm)] reduce:^(NSString *password,NSString *textString,NSString *passwordConfirm){

? ? ? ? if ([password isEqualToString:passwordConfirm] && textString.length > 0) {

? ? ? ? ? ? return @(YES);

? ? ? ? }else{

? ? ? ? ? ? return @(NO);

? ? ? ? }

? ? }];

?? ?

? ? //----------------------------------------RACSignal创建使用--------------------------------------------

//? ? 当一个signal被一个subscriber subscribe后,这个subscriber何时会被移除?答案是当subscribersendCompletesendError时,或者手动调用[disposable dispose]

? ? RACSignal *signal = [RACSignalcreateSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

? ? ? ? NSLog(@"当前值");

? ? ? ? [subscriber sendNext:@"下个值"];

? ? ? ? [subscriber sendCompleted];

? ? ? ? return nil;

? ? }];//创建了一个 signal 但是没有 subscribe 所有上面都不会发生。

?? ?

? ? //单独执行这句会输出? 当前值? 完成1

? ? [signal subscribeCompleted:^{

? ? ? ? NSLog(@"完成了1");

? ? }];

?? ?

? ? //单独执行这句 会输出? 当前值 x2===下个值

? ? [signal subscribeNext:^(id x) {

? ? ? ? NSLog(@"x2===%@",x);

? ? }];

?? ?

? ? //单独执行这句 会输出? 当前值 x3===下个值? 完成了3

? ? [signal subscribeNext:^(id x) {

? ? ? ? NSLog(@"x3====%@",x);

? ? } completed:^{

? ? ? ? NSLog(@"完成了3");

? ? }];

?

?

? ? //---------------------------------------- RACSignal merge zipWith------------------------------------

? ? RACSignal *signalA = [RACSignalcreateSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

? ? ? ? [subscriber sendNext:@"A"];

? ? ? ? return nil;

? ? }];//创建了一个 signal 但是没有 subscribe 所有上面都不会发生。

?? ?

? ? RACSignal *signalB = [RACSignalcreateSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

? ? ? ? [subscriber sendNext:@"B"];

? ? ? ? return nil;

? ? }];

?? ?

? ? RACSignal *mergeSignal = [signalA merge:signalB];//任何一个信号发出都会执行。

? ? [mergeSignal subscribeNext:^(id x) {

? ? ? ? NSLog(@"%@",x);? ///两个输出: A? B

? ? }];

?

? ? RACSignal *zipSignal = [signalA zipWith:signalB];//两个信号都发出才会执行

? ? [zipSignal subscribeNext:^(id x) {

? ? ? ? NSLog(@"%@",x);///会输出一个数组(A ,B <RACTuple: 0x7fd61c82b1d0>

? ? }];

?

? ? RACSignal *combineSignal = [signalA combineLatestWith:signalB];

? ? [combineSignal subscribeNext:^(id x) {

? ? ? ? NSLog(@"%@",x);//会输出一个数组(A ,B? <RACTuple: 0x7fd61c82b1d0>

? ? }];

?? ?

? ? RACSignal *reduceSignal = [RACSignal combineLatest:@[signalA,signalB] reduce:^id(NSString *str1,NSString *str2){

? ? ? ? return [NSString stringWithFormat:@"%@ %@",str1,str2];

? ? }];

? ? [reduceSignal subscribeNext:^(id x) {

? ? ? ? NSLog(@"%@",x);//合并后的字符串 A B

? ? }];

?? ?

? ? //---------------------------------------- RACSubject RACSignal 的子类------------------------------------

?? ?

//? ? subjects 表现为RACSubject类,可以认为是可变的(mutable信号/自定义信号,它是嫁接非RAC代码到Signals世界的桥梁,很有用。嗯。。。这样讲还是很抽象,举个例子吧:

? ? RACSubject *letters = [RACSubject subject];

? ? [letters sendNext:@"a"];

//? ? 可以看到@"a"只是一个NSString对象,要想在水管里顺利流动,就要借RACSubject的力。

?? ?

? ? //---------------------------------------- RACSequence有个属性是 RACSignal---------------------------

//? ? sequence 表现为RACSequence类,可以简单看做是RAC世界的NSArrayRAC增加了-rac_sequence方法,可以使诸如NSArray这些集合类(collection classes)直接转换为RACSequence来使用。

? ? NSArray *arr = [NSArray arrayWithObjects:@"arr1",@"arr2", nil];

? ? NSMutableArray *array = [NSMutableArrayarray];

? ? RACSequence *sequence = [arr rac_sequence];

? ? [[[sequence.signal map:^id(id value) {

? ? ? ? [array addObject:value];

? ? ? ? return array;

? ? }] filter:^BOOL(NSArray *resultArray) {

? ? ? ? if (resultArray.count < 2) {

? ? ? ? ? ? return NO;

? ? ? ? }else{

? ? ? ? ? ? return YES;

? ? ? ? }

? ? }] subscribeNext:^(id x) {

? ? ? ? NSLog(@"x===%@",x);

? ? }];

?

?? ?

? ? //---------------------------------------- scheduler 定时器------------------------------------

//? ? scheduler 表现为RACScheduler类,类似于GCDbut schedulers support cancellationbut schedulers support cancellation, and always execute serially

?? ?

? ? /**

?? ? *??@brief??创建一个定时器信号,每三秒发出一个当时日期值。一共发5次。

?? ? */

? ? RACSignal *signalInterval = [RACSignalinterval:3.0onScheduler:[RACSchedulermainThreadScheduler]];

? ? signalInterval = [signalInterval take:5];//总共5次。

? ? [signalInterval subscribeNext:^(id x) {

? ? ? ? NSLog(@"x====%@",x);///x====2015-12-30 04:05:50 +0000

? ? }];

?

}

ReactiveCocoa 学习笔记

原文:http://zhangmingwei.iteye.com/blog/2267631

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!