RAC学习

2019-05-14  本文已影响0人  marlonxlj

更新时间:2019-6-10

更新内容:Injection 热加载 RAC中 崩溃问题的解决办法

直接使用会崩溃
#pragma mark -- OC 中如果项目中包含RAC,使用injected方法会导致程序崩溃,解决的办法是使用通知的方式@"INJECTION_BUNDLE_NOTIFICATION"
//- (void)injected
//{
//    NSLog(@"I've been injected: %@", self);
//}

解决方法如下:
KK_WeakSelf
    [[[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"INJECTION_BUNDLE_NOTIFICATION" object:nil] takeUntil:[self rac_willDeallocSignal]] subscribeNext:^(NSNotification * _Nullable x) {
        KK_StrongSelf
        [self hotReloadView];
    }];

更新时间:2019-05-14

RAC_Demo下载地址

目录:

1. TextField的使用

2. Slider控制bgView的背景颜色

3. Network网络的处理

4. NSNotice通知事件

5. Tap事件的添加

6. TableViewCell中2个View添加事件

【效果图如下】

iToolsScreenecord019-05-159.53.58.gif

1. TextField的使用

TextField的使用情况,用户输入用户名,密码大于6位,改变登录按钮的背景色和是否可以点击的事件。

- (void)settingStatus{
    
    //按钮的使能
    RAC(self.loginBtn,backgroundColor) = [RACSignal combineLatest:@[self.userNameTextField.rac_textSignal,self.userPwdTextField.rac_textSignal] reduce:^id (NSString* name,NSString *pwd){
        BOOL enable = [name length] > 0 && [pwd length] > 6;
        self.loginBtn.enabled = enable;
        return enable ? [UIColor redColor] : [UIColor lightGrayColor];
    }];
    
    [[self.loginBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
        
        NSLog(@"n:%@,p:%@",self.userNameTextField.text,self.userPwdTextField.text);
    }];
}

2. Slider控制bgView的背景颜色

- (void)settingSubView{
    //绑定3个信号
    RACSignal *redSignal = [self bindSlider:self.redSlider textField:self.redTextField];
    RACSignal *blueSignal = [self bindSlider:self.blueSlider textField:self.blueTextField];
    RACSignal *yellowSignal = [self bindSlider:self.yellowSlider textField:self.yellowTextField];
    
    RACSignal *changeSignal = [[RACSignal combineLatest:@[redSignal,blueSignal,yellowSignal]] map:^id _Nullable(RACTuple * value) {
        return [UIColor colorWithRed:[value[0] floatValue] green:[value[1] floatValue] blue:[value[2] floatValue] alpha:1];
    }];
    //这个宏传入的参数: 一个是需要修改的对象,一个是这个对象的熟悉,最后是给她进行赋值。
    RAC(self.showBgView,backgroundColor) = changeSignal;
}

- (RACSignal *)bindSlider:(UISlider *)slider textField:(UITextField *)textField{
    
    RACSignal *textSignal = [[textField rac_textSignal] take:1];
    
    //终端
    RACChannelTerminal *signalSlider = [slider rac_newValueChannelWithNilValue:nil];
    RACChannelTerminal *signalText = [textField rac_newTextChannel];
    
    //文本终端订阅slider终端
    [signalText subscribe:signalSlider];
    //slider订阅text终端
    [[signalSlider map:^id _Nullable(id  _Nullable value) {
        return [NSString stringWithFormat:@"%.02f",[value floatValue]];
    }] subscribe:signalText];
    
    return [[signalText merge:signalSlider] merge:textSignal];
}

3. Network网络的处理



- (void)startRequest{
    //1、单个请求
    [[self.signalBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
        [self requestSignal];
    }];
    
    //2、异步请求
    [[self.asyncBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
        [self requestAsyncFunc];
    }];
    
    //3、同步请求,都执行完后才操作
    [[self.sysBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
        [self requestSyncFunc];
    }];
    
    //4、其他请求
    __weak typeof(self) weakSelf = self;
    [[self.otherBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
        [weakSelf showTextInfo:@"暂无内容"];
    }];
}

- (void)requestSignal{
    __weak typeof(self) weakSelf = self;
    [[self signalFromJson:urlPath cityName:@"成都"] subscribeNext:^(id  _Nullable x) {
        NSString *tmpStr = [NSString stringWithFormat:@"%@",x[@"result"]];
        [weakSelf showTextInfo:tmpStr];
    }];
}

- (void)requestAsyncFunc{
    __weak typeof(self) weakSelf = self;
    RACSignal *reqSignal = [self signalFromJson:urlPath cityName:@"上海"];
    RACSignal *reqSignal1 = [self signalFromJson:urlPath cityName:@"杭州"];
    RACSignal *reqSignal2 = [self signalFromJson:urlPath cityName:@"南京"];
    
    //2、同步执行,三个都执行完后才返回结果
    [[RACSignal combineLatest:@[reqSignal,reqSignal1,reqSignal2]] subscribeNext:^(RACTuple * _Nullable x) {
        NSArray *array = (NSArray *)x;
        NSString *tmpStr = [NSString stringWithFormat:@"返回的结果都在这个数组里面,没有顺序,执行完后才有结果:%ld个结果",array.count];
        [weakSelf showTextInfo:tmpStr];
    }];
    
}

- (void)requestSyncFunc{
    __weak typeof(self) weakSelf = self;
    RACSignal *reqSignal = [self signalFromJson:urlPath cityName:@"上海"];
    RACSignal *reqSignal1 = [self signalFromJson:urlPath cityName:@"杭州"];
    RACSignal *reqSignal2 = [self signalFromJson:urlPath cityName:@"南京"];
   
    //1、同步请求
    [[[reqSignal merge:reqSignal1] merge:reqSignal2] subscribeNext:^(id  _Nullable x) {
        NSString *tmpStr = [NSString stringWithFormat:@"会有三次的请求返回,每次的结果都是:\n %@",x[@"result"]];
        //这里会把三个请求的结果依次在这里返回回来
        [weakSelf showTextInfo:tmpStr];
    }];
}

- (void)otherRequestFunc{
    __weak typeof(self) weakSelf = self;
    //1、顺序执行,执行完第一个,再执行第二个,第二个完成再执行第三个
    RACSignal *reqSignal = [self signalFromJson:urlPath cityName:@"上海"];
    RACSignal *reqSignal1 = [self signalFromJson:urlPath cityName:@"杭州"];
    RACSignal *reqSignal2 = [self signalFromJson:urlPath cityName:@"南京"];
    [[[reqSignal then:^RACSignal * _Nonnull{
        NSLog(@"第一个信号请求完成");
        return reqSignal1;
    }] then:^RACSignal * _Nonnull{
        NSLog(@"第二个信号请求完成");
        return reqSignal2;
    }] subscribeNext:^(id  _Nullable x) {
        NSString *tmpStr = [NSString stringWithFormat:@"%@",x[@"result"]];
        //这里会把三个请求的结果依次在这里返回回来
        [weakSelf showTextInfo:tmpStr];
        NSLog(@"第三个信号请求完成");
    }];
}

- (RACSignal *)signalFromJson:(NSString *)urlStr cityName:(NSString *)cityName{
    
    return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        
        NSString *urlTmp = [NSString stringWithFormat:@"%@?cityname=%@&dtype=%@&format=%@&key=%@",urlStr,cityName,@"json",@(1),@"bd1a721f3c8dae7c601c2b024afb367b"];
        //将网址转化为UTF8编码
        NSString *urlStringUTF8 = [urlTmp stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlStringUTF8]];
        request.HTTPMethod = @"GET";
        NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
        NSURLSessionTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            if (error) {
                [subscriber sendError:error];
            }
            else{
                NSError *e;
                NSArray *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&e];
                if (e) {
                    [subscriber sendError:e];
                }
                else{
                    [subscriber sendNext:jsonDict];
                    [subscriber sendCompleted];
                }
            }
        }];
        
        [dataTask resume];
        
        return [RACDisposable disposableWithBlock:^{
            
        }];
    }];
}

- (void)showTextInfo:(NSString *)info{
    //注意:这里一定要在主线程里面更新赋值,不然会造成崩溃的问题.
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_main_queue(), ^{
        weakSelf.showTextView.text = info;
    });
}

4. NSNotice通知事件

发送通知,由于我是直接从Controller的TableViewCell中push过去的,所以处理有点不一样。
if ([vcStr isEqualToString:@"NSNotionController"]) {
        //无论在push操作前或后发送通知,当push到SecondViewController中时,是接收不到通知的。
        //通过NSLog(@"Thread:%@",[NSThread currentThread]);或[NSOperationQueue currentQueue]我们可以查到push时的线程和接收通知时的线程为主线程,输出:Thread:<NSThread: 0x170072d80>{number = 1, name = main}。
        //顺序还有影响,如果把通知放在push之前,在接收通知的时候是收不到的,放在主线程的后面才可以收到
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [self.navigationController pushViewController:[NSClassFromString(vcStr) new] animated:YES];
        }];
        
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
           [[NSNotificationCenter defaultCenter] postNotificationName:@"NSNotionController" object:@"TestNotice"];
        }];
    }

接收通知
[[[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"NSNotionController" object:nil] takeUntil:[self rac_willDeallocSignal]] subscribeNext:^(NSNotification * _Nullable x) {
      dispatch_async(dispatch_get_main_queue(), ^{
          weakSelf.noLable.text = x.object;
      });
  }];

5. Tap事件的添加

- (void)addTapForView{
    UITapGestureRecognizer *redTap = [[UITapGestureRecognizer alloc] init];
    [self.redView addGestureRecognizer:redTap];
    [[redTap rac_gestureSignal] subscribeNext:^(__kindof UIGestureRecognizer * _Nullable x) {
        [self showLableInfo:x];
    }];
    
    UITapGestureRecognizer *yellowTap = [[UITapGestureRecognizer alloc] init];
    [self.yellowView addGestureRecognizer:yellowTap];
    [[yellowTap rac_gestureSignal] subscribeNext:^(__kindof UIGestureRecognizer * _Nullable x) {
        [self showLableInfo:x];
    }];
}

- (void)showLableInfo:(UIGestureRecognizer *)taps{
    self.showLable.text = [NSString stringWithFormat:@"Tag:%ld",taps.view.tag];
}

6. TableViewCell中2个View添加事件

Cell中的代码:
- (void)addTapForImageView{
    UITapGestureRecognizer *redTap = [[UITapGestureRecognizer alloc] init];
    [self.leftImageView addGestureRecognizer:redTap];
    self.leftImageView.tag = 100;
    self.leftImageView.layer.masksToBounds = YES;
    self.leftImageView.layer.cornerRadius = 3;
    [[redTap rac_gestureSignal] subscribeNext:^(__kindof UIGestureRecognizer * _Nullable x) {
        [self showLableInfo:x];
    }];
    
    UITapGestureRecognizer *yellowTap = [[UITapGestureRecognizer alloc] init];
    [self.rightImageView addGestureRecognizer:yellowTap];
    self.rightImageView.layer.masksToBounds = YES;
    self.rightImageView.layer.cornerRadius = 3;
    self.rightImageView.tag = 101;
    [[yellowTap rac_gestureSignal] subscribeNext:^(__kindof UIGestureRecognizer * _Nullable x) {
        [self showLableInfo:x];
    }];
    
    self.subject = [RACSubject subject];
}
- (void)showLableInfo:(UIGestureRecognizer *)taps{
    [self.subject sendNext:taps];
    //不能加这句话因为,如果已经完成了,就不能在接收发送的消息了
//    [self.subject sendCompleted];
    
}

Controller中的代码:
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
    TapTableControllerCell *cell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];
    
    UIView *bgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 40)];
    
    UILabel *showLable = [[UILabel alloc] initWithFrame:CGRectMake(20, 0, CGRectGetWidth(bgView.frame)-40,CGRectGetHeight(bgView.frame))];
    showLable.font = [UIFont systemFontOfSize:16];
    showLable.text = @"点击了:";
    [bgView addSubview:showLable];
    [[cell.subject takeUntil:cell.rac_prepareForReuseSignal] subscribeNext:^(UIGestureRecognizer * x) {
        NSString *tmp = [NSString stringWithFormat:@"点击了: Tag:%ld",x.view.tag];
        showLable.text = tmp;
    }];
    
    return bgView;
}

上一篇下一篇

猜你喜欢

热点阅读