whuizhou 2015-12-30
Tip: 自己开发了好玩的APP: 《小明搜索》(App Store上搜索:"小明搜索")
[点击下载 "小明搜索"](https://itunes.apple.com/cn/app/小明搜索/id1378798470?l=en&mt=8)
1、集必应、百度、搜狗为一体的搜索平台
2、用户随意收藏或添加自己喜欢的网站
3、网页文字播放功能
4、收藏网页的视频,本地播放
5、附加常用小工具
6、后台播放网页音频
7、3D Touch提供便捷入口
完全自定义的搜索助手,简约的爱不释手~
该APP不断完善中~
#pragma mark - 各种方便的block封装 ReactiveCocoa
/*
概述:
可以把信号想象成水龙头,只不过里面不是水,而是玻璃球(value),直径跟水管的内径一样,这样就能保证玻璃球是依次排列,不会出现并排的情况(数据都是线性处理的,不会出现并发情况)。水龙头的开关默认是关的,除非有了接收方(subscriber),才会打开。这样只要有新的玻璃球进来,就会自动传送给接收方。可以在水龙头上加一个过滤嘴(filter),不符合的不让通过,也可以加一个改动装置,把球改变成符合自己的需求(map)。也可以把多个水龙头合并成一个新的水龙头(combineLatest:reduce:),这样只要其中的一个水龙头有玻璃球出来,这个新合并的水龙头就会得到这个球。
具体使用:
当一个signal被一个subscriber subscribe后,这个subscriber何时会被移除?答案是当subscriber被sendComplete或sendError时,或者手动调用[disposable dispose]。
当subscriber被dispose后,所有该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并不会在调用addObject或removeObject时发送通知
//------------------------------------通知监听----------------------------------------
[[[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何时会被移除?答案是当subscriber被sendComplete或sendError时,或者手动调用[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世界的NSArray,RAC增加了-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类,类似于GCD,but 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
}];
}