蘑菇街的页面框架实现了页面跳转和UIViewController无关,ReactiveCocoa实现了view或UIViewController发送请求被抽象为viewModel统一处理,这样就解藕了MVVM的架构。RACSignal就是对各种处理再抽象一层,让我们使用更方便。
第1种:代替代理
RACSignal代替代理很简单,不需要像代理一样设置协议,不需要像block一样定义block类型和赋值,通过下面的一句话监听事件就能实现。
@weakify(self);

  1. [[_tipGBHeadInfoPanel rac_signalForSelector:@selector(closeAction:)] subscribeNext:^(id x) {
    @strongify(self);
    }];
    2.[[self rac_signalForSelector:@selector(initTabviewHeaderTitle)] subscribeNext:^(id x) {
    NSLog(@“控制器调用了initData”);
    }];
    第2种:代替KVO
  2. [self.errorSuccessPanel rac_observeKeyPath:@“bannerTimerCount” options:NSKeyValueObservingOptionNew observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
    // 只要监听的属性一改变调用
    if(affectedOnlyLastComponent)
    {
    self.errorSuccessPanel.errorSuccessInfoLabel.text = [NSString stringWithFormat:@"%.0f", self.errorSuccessPanel.bannerTimerCount];
    }
    NSLog(@“value :%@,affectedOnlyLastComponent:%d,%.0f”,value,affectedOnlyLastComponent,self.errorSuccessPanel.bannerTimerCount);
    }];
  3. [self.errorSuccessPanel rac_observeKeyPath:@“bannerTimerCount” options:NSKeyValueObservingOptionNew observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
    // 只要监听的属性一改变调用
    NSLog(@“affectedOnlyLastComponent:%.0f”,self.errorSuccessPanel.bannerTimerCount);
    }];
  4. [RACObserve(self, self.bannerTimerCount)
    subscribeNext:^(NSString* x){
    NSLog(@“x:%@”, x);
    }];
    第3种:监听事件
    为你省下添加事件的麻烦。
    1.[[_rightBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
    [MGJRouter openURL:@“gb://gotoMyOrderList”];
    }];
    2. _rightBtn.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
    NSLog(@“按钮点击”);
    [MGJRouter openURL:@“gb://gotoMyOrderList”];
    return [RACSignal empty];
    }];
    第4种:代替通知
    合并了通知的添加和通知处理函数。
    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {
    NSLog(@"%@",x);
    }];
    第5种:监听文本框文字改变
    [_text.rac_textSignal subscribeNext:^(id x) {
    // x:文本框的文字
    NSLog(@"_text:%@",x);
    }];
    第6种:处理当界面有多次请求时,需要都获取到数据时,才能展示界面
    RACSignal *requestHot = [RACSignal createSignal:^RACDisposable *(id subscriber) {
    NSLog(@“请求最热商品”);
    [subscriber sendNext:@“获取最热商品”];
    [subscriber sendCompleted];
    return nil;
    }];
    RACSignal *requestNew = [RACSignal createSignal:^RACDisposable *(id subscriber) {
    NSLog(@“请求最新商品”);
    //下面这一语句一定要有
    [subscriber sendNext:@“获取最新商品”];
    [subscriber sendCompleted];
    return nil;
    }];
// Selector调用:当所有信号都发送数据的时候调用
// 数组存放信号
// Selector注意点:参数根据数组元素决定
// Selector方法参数类型,就是信号传递出来数据

[self rac_liftSelector:@selector(updateUI:data2:) withSignalsFromArray:@[requestHot,requestNew]];

// 只要两个请求都请求完成的时候才会调用

- (void)updateUI:(NSString *)data1 data2:(NSString *)data2
{
NSLog(@"%@ %@",data1,data2);
}

第7种:MVMM模式下的请求发送
定义部分:

  • (void)setupRACCommand
    {
    @weakify(self);
    self.cancelOrderCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
    return [RACSignal createSignal:^RACDisposable *(id subscriber) {
    @strongify(self);
    self.cancelApi.setParams(input);
    [[YXRequestClient sharedClient] loadDataWithApi:self.cancelApi successBlock:^(NSDictionary *result) {
    [subscriber sendNext:result];
    [subscriber sendCompleted];
    } failureBlock:^(NSError *error) {
    [subscriber sendError:error];
    }];
    return nil;
    }];
    }];
    }
    使用部分:
  • (void)cancelUseCar:(NSString *)itemId
    {
    [[_orderDetailTripModel.cancelOrderCommand execute:@{@“revokeCode”:itemId?itemId:@"", @“orderNo”😡(_orderDetailTripEntity.orderNo)?@(_orderDetailTripEntity.orderNo)😡"", @“reqToken”:[GBUserInfo sharedUserInfo].user.reqToken?[GBUserInfo sharedUserInfo].user.reqToken:@""}] subscribeNext:^(id x) {
    [[YXNavigationController currentNavigationController] popViewControllerWithAnimation:AnimationSlideHorizontal];
    } error:^(NSError *error) {
    [[GBNoticeView currentNotice] showErrorNotice:error.domain];
    }];
    }
    第8种:同时监控多个代理事件,请求事件或信号
    merge:多个信号合并成一个信号,任何一个信号有新值就会调用
    zipWith:把两个信号压缩成一个信号,只有当两个信号同时发出信号内容时,并且把两个信号的内容合并成一个元祖,才会触发压缩流的next事件。 压缩成一个信号。zipWith当一个界面多个请求的时候,要等所有请求完成才更新UI
    等所有信号都发送内容的时候才会调用
    发送信号 交互顺序,元组内元素的顺序不会变,跟发送的顺序无关,而是跟压缩的顺序有关[signalA zipWith:signalB]—先是A后是B。
    zipWith的功能本来就该服务器来合并多个请求,但是基本上服务器开发人员都反对把多个业务无关的请求合并为一个请求(一般需要查不同的数据库表,甚至访问不同服务化的服务器)。我们做app的没有人和咱们合作,只能自己合并请求处理了。

zipWith使用例子

-(void)searchId
{
//zipWith:把两个信号压缩成一个信号,只有当两个信号同时发出信号内容时,并且把两个信号的内容合并成一个元祖,才会触发压缩流的next事件。
@weakify(self);
// 创建信号findAllProductClassSignal
RACSignal *findAllProductClassSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[[self.searchViewModel.findAllProductClassCommand execute:[NSMutableArray array]]subscribeNext:^(NSMutableArray *productClasssList)
{
@strongify(self);
self.productClasssList = productClasssList;
[subscriber sendNext:@"findAllProductClassSignal"];
[subscriber sendCompleted]; // 必须要调用sendCompleted方法!
} error:^(NSError *error) {
NSLog(@"error is %@",error);
}];
return nil;
}];

// 创建信号getArtOrgSignal
RACSignal *getArtOrgSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[[self.searchViewModel.getArtOrgCommand execute:[NSMutableArray array]]subscribeNext:^(NSMutableArray *artOrgsList)
{
@strongify(self);
self.artOrgsList = artOrgsList;
[subscriber sendNext:@"getArtOrgSignal"];
[subscriber sendCompleted]; // 必须要调用sendCompleted方法!
} error:^(NSError *error) {
NSLog(@"error is %@",error);
}];
return nil;
}];

// 压缩成一个信号
// **-zipWith-**: 当一个界面多个请求的时候,要等所有请求完成才更新UI
// 等所有信号都发送内容的时候才会调用
// 发送信号 交互顺序,元组内元素的顺序不会变,跟发送的顺序无关,而是跟压缩的顺序有关[signalA zipWith:signalB]---先是A后是B
RACSignal *zipSignal = [findAllProductClassSignal zipWith:getArtOrgSignal];
[zipSignal subscribeNext:^(id x) {
NSLog(@"%@", x); //所有的值都被包装成了元组
self.isSearchIdSuccess = YES;
[self setupView];
}];
}

merge的使用例子

-(void)searchId
{
@weakify(self);
// 创建信号findAllProductClassSignal
RACSignal *findAllProductClassSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[[self.searchViewModel.findAllProductClassCommand execute:[NSMutableArray array]]subscribeNext:^(NSMutableArray *productClasssList)
{
@strongify(self);
self.productClasssList = productClasssList;
[subscriber sendNext:@"findAllProductClassSignal"];
[subscriber sendCompleted]; // 必须要调用sendCompleted方法!
} error:^(NSError *error) {
NSLog(@"error is %@",error);
}];
return nil;
}];

// 创建信号getArtOrgSignal
RACSignal *getArtOrgSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[[self.searchViewModel.getArtOrgCommand execute:[NSMutableArray array]]subscribeNext:^(NSMutableArray *artOrgsList)
{
@strongify(self);
self.artOrgsList = artOrgsList;
[subscriber sendNext:@"getArtOrgSignal"];
[subscriber sendCompleted]; // 必须要调用sendCompleted方法!
} error:^(NSError *error) {
NSLog(@"error is %@",error);
}];
return nil;
}];
//组合信号
RACSignal *mergeSignal = [findAllProductClassSignal merge:getArtOrgSignal];
// 订阅信号
[mergeSignal subscribeNext:^(id x) {
NSLog(@"%@", x);
self.isSearchIdSuccess = YES;
[self setupView];
}];
}

下面是RAC部分实现代码:

@weakify(self);
[[_tipGBHeadInfoPanel rac_signalForSelector:@selector(closeAction:)] subscribeNext:^(id x) {
@strongify(self);
self.errorSuccessPanel = [GBErrorSuccessPanel showSuccessNotice:@"test"];
[[self.errorSuccessPanel rac_signalForSelector:@selector(configAction:)] subscribeNext:^(id x) {
@strongify(self);
NSLog(@"self.errorSuccessPanel:%@;self.errorSuccessPanel.errorSuccessInfoLabel:%@, self.errorSuccessPanel.errorSuccessInfoLabel.text:%@", self.errorSuccessPanel,self.errorSuccessPanel.errorSuccessInfoLabel, self.errorSuccessPanel.errorSuccessInfoLabel.text);
self.errorSuccessPanel.errorSuccessInfoLabel.text = @"rac_signal";
NSLog(@"self.errorSuccessPanel.errorSuccessInfoLabel.text:%@", self.errorSuccessPanel.errorSuccessInfoLabel.text);
}];

// [[self.errorSuccessPanel rac_valuesForKeyPath:@“bannerTimerCount” observer:nil] subscribeNext:^(id x) {
// self.errorSuccessPanel.errorSuccessInfoLabel.text = [NSString stringWithFormat:@"%.0f", self.errorSuccessPanel.bannerTimerCount];
// }];
// [self.errorSuccessPanel rac_valuesForKeyPath:@“bannerTimerCount” options:NSKeyValueObservingOptionNew observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
// //value就是frame变化之后的值
// NSLog(@"----%@", value);
// }];

    [self.errorSuccessPanel rac_observeKeyPath:@"bannerTimerCount" options:NSKeyValueObservingOptionNew observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
// 只要监听的属性一改变调用
if(affectedOnlyLastComponent)
{
self.errorSuccessPanel.errorSuccessInfoLabel.text = [NSString stringWithFormat:@"%.0f", self.errorSuccessPanel.bannerTimerCount];
}
NSLog(@"value :%@,affectedOnlyLastComponent:%d,%.0f",value,affectedOnlyLastComponent,self.errorSuccessPanel.bannerTimerCount);
}];

// [self.errorSuccessPanel rac_observeKeyPath:@“bannerTimerCount” options:NSKeyValueObservingOptionNew observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
// // 只要监听的属性一改变调用
// NSLog(@“affectedOnlyLastComponent:%.0f”,self.errorSuccessPanel.bannerTimerCount);
// }];
// [[NSNotificationCenter defaultCenter] removeObserver:self];
// [self endEditing:YES];
// // self.alertContentBackgroundView.frame=CGRectMake(0, kScreenHeight - height, kScreenWidth, height);
// self.alertContentBackgroundView.top = kScreenHeight - height;
// self.alertBackgroundView.alpha = 0.9;
// [UIView animateWithDuration:0.2 animations:^{
// self.alertBackgroundView.alpha = 0.0f;
// // self.alertContentBackgroundView.frame=CGRectMake(0, kScreenHeight, kScreenWidth, height);
// self.alertContentBackgroundView.top = kScreenHeight;
// } completion:^(BOOL finished) {
// [self endEditing:YES];
// self.currentWindow = nil;
// [self removeFromSuperview];
// }];
}];

一个测试弹出框的头文件:
#import <UIKit/UIKit.h>
@interface GBErrorSuccessPanel : UIView
@property (nonatomic,strong) NSTimer *bannerTimer;
@property (nonatomic,strong) GBErrorSuccessPanel *errorSuccessPanel;
@property (nonatomic,assign) CGFloat bannerTimerCount;
@property (nonatomic,strong) UIButton *configBtn;
@property (nonatomic,strong) UILabel *displayInfoLab;
@property (nonatomic,strong) UILabel *errorSuccessInfoLabel;
@property (nonatomic,strong) UIButton *hitBtn;
@property (nonatomic,strong) UITextField *text;

  • (instancetype)showSuccessNotice:(NSString *)notice;
  • (instancetype)showErrorNotice:(NSString *)notice;
  • (void)configAction:(UIButton *)sender;
    @end

一个测试弹出框的实现文件:
#import “GBErrorSuccessPanel.h”
#import “NSObject+RACPropertySubscribing.h”
@interface GBErrorSuccessPanel ()
@property (nonatomic,strong) UIView *errorSuccessBackgroundView;
@property (nonatomic,strong) UIImageView *errorSuccessIconImageView;
@property (nonatomic,strong) UIPanGestureRecognizer *painRecognize;
@property (nonatomic,assign) UIWindowLevel currentWindowLevel;
@property (nonatomic,strong) UIWindow *statusWindow;//当前window
@end
@implementation GBErrorSuccessPanel

  • (instancetype)showSuccessNotice:(NSString *)notice
    {
    if((notice == nil) || ![notice isKindOfClass:[NSString class]] || (notice.length == 0))
    {
    return nil;
    }
    return [[self alloc] createPanelWithIsSucess:YES
    message:notice];
    }
  • (instancetype)showErrorNotice:(NSString *)notice
    {
    if((notice == nil) || ![notice isKindOfClass:[NSString class]] || (notice.length == 0))
    {
    return nil;
    }
    return [[self alloc] createPanelWithIsSucess:NO
    message:notice];
    }
  • (instancetype)createPanelWithIsSucess:(BOOL)isSucess
    message:(NSString *)message;
    {
    return [self initPanelWithIsSucess:isSucess
    message:message];
    }
  • (instancetype)initPanelWithIsSucess:(BOOL)isSucess
    message:(NSString *)message;
    {
    _statusWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, FULL_WIDTH, 64)];
    _statusWindow.windowLevel = UIWindowLevelStatusBar + 1;
    _statusWindow.opaque = NO;
    [self.statusWindow makeKeyAndVisible];
    self.bannerTimerCount = 8;//BANNER_TIMER_MAX_COUNT;
    NSLog(@“self.bannerTimerCount:%.1f”, (self.bannerTimerCount));
    if(self.errorSuccessPanel != nil)
    {
    [self updateSingleErrorSuccessPanelWithIsSucess:isSucess message:message];
    return nil;
    }
    GBErrorSuccessPanel *errorSuccessPanel = [self initFramPanelWithIsSucess:isSucess
    message:message];
    if(errorSuccessPanel == nil)
    {
    return nil;
    };
    self.errorSuccessPanel = errorSuccessPanel;
    [_statusWindow addSubview:errorSuccessPanel];
    errorSuccessPanel.sd_layout
    .leftSpaceToView(_statusWindow, 0)
    .rightSpaceToView(_statusWindow, 0)
    .topSpaceToView(_statusWindow, 0)
    .heightIs(64); // 设置高度约束
    errorSuccessPanel.frame=CGRectMake(0, -64, kScreenWidth, 64);
    [UIView animateWithDuration:0.05 animations:^{
    errorSuccessPanel.frame=CGRectMake(0, 0, kScreenWidth, 64);
    }];
    return errorSuccessPanel;
    }
    -(void)bannerGrogress
    {
    NSLog(@“bannerGrogress nowTime:%lld”, (long long)([[NSDate date] timeIntervalSince1970] * 1000));
    NSLog(@“bannerGrogress self.bannerTimerCount:%.1f”, (self.bannerTimerCount));
    if(self.bannerTimerCount > 0)
    {
    self.bannerTimerCount = self.bannerTimerCount - 0.1;
    if(self.bannerTimerCount <= 0)
    {
    self.bannerTimerCount = 0;
    if(self.errorSuccessPanel != nil)
    {
    [self.bannerTimer setFireDate:[NSDate distantFuture]];
    [UIView animateWithDuration:0.05 animations:^{
    self.errorSuccessPanel.frame=CGRectMake(0, -64, kScreenWidth, 64);
    self.errorSuccessPanel.statusWindow = nil;
    [self.errorSuccessPanel removeFromSuperview];
    self.errorSuccessPanel = nil;
    [self endEditing:YES];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    }];
    return;
    }
    else
    {
    [self.bannerTimer setFireDate:[NSDate distantFuture]];
    }
    }
    else
    {
    if(self.errorSuccessPanel != nil)
    {
    self.errorSuccessPanel.errorSuccessBackgroundView.hidden = NO;
    }
    }
    }
    else
    {
    //防范式编程,原理上不会出现,只是逻辑上的补充
    self.bannerTimerCount = 0;
    if(self.errorSuccessPanel != nil)
    {
    [self.bannerTimer setFireDate:[NSDate distantFuture]];
    [self.errorSuccessPanel removeFromSuperview];
    self.errorSuccessPanel = nil;
    [self endEditing:YES];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    return;
    }
    else
    {
    [self.bannerTimer setFireDate:[NSDate distantFuture]];
    }
    }
    }
  • (instancetype)initFramPanelWithIsSucess:(BOOL)isSucess
    message:(NSString *)message;
    {
    if(![message isKindOfClass:[NSString class]])
    {
    return nil;
    }
    if (self = [super init]) {
    [self initSubPanelWithIsSucess:isSucess
    message:message];
    }
    return self;
    }
  • (void)updateSingleErrorSuccessPanelWithIsSucess:(BOOL)isSucess
    message:(NSString *)message;
    {
    if(!isSucess)
    {
    UIImage *image = [[UIImage imageNamed:@“common_icon_tips_err”] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    self.errorSuccessPanel.errorSuccessIconImageView.image = image;
    self.errorSuccessPanel.errorSuccessBackgroundView.backgroundColor = [UIColor colorWithHexString:@“0XD26469”];//RGB(210, 100, 105);
    self.errorSuccessPanel.errorSuccessInfoLabel.text = message;
    }
    else
    {
    UIImage *image = [[UIImage imageNamed:@“common_icon_tips_success”] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    self.errorSuccessPanel.errorSuccessIconImageView.image = image;
    self.errorSuccessPanel.errorSuccessBackgroundView.backgroundColor = HIGH_LIGHTED_LINE_COLOR;//RGB(210, 100, 105);
    self.errorSuccessPanel.errorSuccessInfoLabel.text = message;
    }
    [self.errorSuccessPanel updateLayout];
    }
  • (void)initSubPanelWithIsSucess:(BOOL)isSucess
    message:(NSString *)message;
    {
    NSLog(@“initSubPanelWithIsSucess [self.bannerTimer isValid] : %d”, [self.bannerTimer isValid]);
    if(![self.bannerTimer isValid])
    {
    NSLog(@“initSubPanelWithIsSucess nowTime:%lld”, (long long)([[NSDate date] timeIntervalSince1970] * 1000));
    @weakify(self);
    self.bannerTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 block:^(NSTimer * _Nonnull timer) {
    @strongify(self);
    [self bannerGrogress];
    } repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:self.bannerTimer forMode:NSRunLoopCommonModes];
    }
    else
    {
    NSLog(@“initSubPanelWithIsSucess nowTime:%lld”, (long long)([[NSDate date] timeIntervalSince1970] * 1000));
  [self.bannerTimer setFireDate:[NSDate date]];

}
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {

  NSLog(@"%@",x);

}];

_errorSuccessBackgroundView = [UIView new];
[self addSubview:_errorSuccessBackgroundView];
_errorSuccessBackgroundView.hidden = NO;
_painRecognize = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(painAction:)];
_painRecognize.maximumNumberOfTouches = 1;
[_errorSuccessBackgroundView addGestureRecognizer:_painRecognize];
_errorSuccessBackgroundView.layer.shadowColor = (RGBA(0, 0, 0, 1)).CGColor;
_errorSuccessBackgroundView.layer.shadowOffset = CGSizeMake(0,3);//shadowOffset阴影偏移,x向右偏移4,y向下偏移4,默认(0, -3),这个跟shadowRadius配合使用
_errorSuccessBackgroundView.layer.shadowOpacity = 0.3;//阴影透明度,默认0
_errorSuccessBackgroundView.layer.shadowRadius = 20;//阴影半径,默认3

_errorSuccessIconImageView = [UIImageView new];
[_errorSuccessBackgroundView addSubview:_errorSuccessIconImageView];

//错误提示
_errorSuccessInfoLabel = [UILabel new];
_errorSuccessInfoLabel.text = message;
_errorSuccessInfoLabel.font = [UIFont systemFontOfSize:13];
_errorSuccessInfoLabel.textColor = [UIColor whiteColor];
_errorSuccessInfoLabel.textAlignment = NSTextAlignmentLeft;
_errorSuccessInfoLabel.numberOfLines = 0;
[_errorSuccessBackgroundView addSubview:_errorSuccessInfoLabel];
_errorSuccessInfoLabel.hidden = NO;
if(!isSucess)
{
UIImage *image = [[UIImage imageNamed:@“common_icon_tips_err”] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
_errorSuccessIconImageView.image = image;
_errorSuccessBackgroundView.backgroundColor = [UIColor colorWithHexString:@“0XD26469”];//RGB(210, 100, 105);
}
else
{
UIImage *image = [[UIImage imageNamed:@“common_icon_tips_success”] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
_errorSuccessIconImageView.image = image;
_errorSuccessBackgroundView.backgroundColor = HIGH_LIGHTED_LINE_COLOR;//RGB(210, 100, 105);
}
_configBtn = [UIButton new];
[_configBtn setTitle:@“代替代理” forState:UIControlStateNormal];
[_configBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
_configBtn.titleLabel.font = [UIFont systemFontOfSize:14];
_configBtn.titleLabel.textAlignment = NSTextAlignmentCenter;
[_configBtn addTarget:self action:@selector(configAction:) forControlEvents:UIControlEventTouchUpInside];
[_errorSuccessBackgroundView addSubview:_configBtn];

_hitBtn = [UIButton new];
[_hitBtn setTitle:@“监听事件” forState:UIControlStateNormal];
[_hitBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
_hitBtn.titleLabel.font = [UIFont systemFontOfSize:14];
_hitBtn.titleLabel.textAlignment = NSTextAlignmentCenter;
[_errorSuccessBackgroundView addSubview:_hitBtn];
// [[_hitBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
// NSLog(@“代替代理:按钮被点击%@”,x);
// }];
_hitBtn.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
NSLog(@“代替代理:按钮点击”);
return [RACSignal empty];
}];

//输入文本框
_text = [UITextField new];
_text.text = @"";
_text.placeholder = @“代替通知&监听文本框文字改变”;
[_text setValue:[UIColor yellowColor] forKeyPath:@"_placeholderLabel.textColor"];
[_text setValue:[UIFont boldSystemFontOfSize:9] forKeyPath:@"_placeholderLabel.font"];
_text.font = [UIFont boldSystemFontOfSize:9];
_text.textColor = [UIColor colorWithHexString:@“0X282E33”];
_text.clearButtonMode = UITextFieldViewModeWhileEditing;
_text.textAlignment = NSTextAlignmentLeft;
_text.keyboardType = UIKeyboardTypeNumberPad;
_text.userInteractionEnabled = YES;
_text.tintColor = [UIColor colorWithHexString:@“0X0F9B70”];
_text.backgroundColor = [UIColor clearColor];
[_errorSuccessBackgroundView addSubview:_text];
[_text.rac_textSignal subscribeNext:^(id x) {
// x:文本框的文字
NSLog(@"_text:%@",x);
}];

[self unitsSdLayoutWithIsSucess:isSucess];
RACSignal *requestHot = [RACSignal createSignal:^RACDisposable *(id subscriber) {
NSLog(@“请求最热商品”);
[subscriber sendNext:@“获取最热商品”];
return nil;
}];

RACSignal *requestNew = [RACSignal createSignal:^RACDisposable *(id subscriber) {
NSLog(@“请求最新商品”);
[subscriber sendNext:@“获取最新商品”];
return nil;
}];

// Selector调用:当所有信号都发送数据的时候调用
// 数组存放信号
// Selector注意点:参数根据数组元素决定
// Selector方法参数类型,就是信号传递出来数据
[self rac_liftSelector:@selector(updateUI:data2:) withSignalsFromArray:@[requestHot,requestNew]];
// [RACObserve(_errorSuccessInfoLabel.text,self.text) subscribeNext:^(id x) {
// NSLog(@“success”);
// }];
[RACObserve(self, self.bannerTimerCount)
subscribeNext:^(NSString* x){
NSLog(@“x:%@”, x);
}];
}
// 只要两个请求都请求完成的时候才会调用

  • (void)updateUI:(NSString *)data1 data2:(NSString *)data2
    {
    NSLog(@"%@ %@",data1,data2);
    }

-(void)unitsSdLayoutWithIsSucess:(BOOL)isSucess
{

_errorSuccessBackgroundView.sd_layout
.leftSpaceToView(self, 0)
.rightSpaceToView(self, 0)
.topSpaceToView(self, 0)
.heightIs(64); // 设置高度约束
UIImage *image = nil;
if(!isSucess)
{
image = [[UIImage imageNamed:@"common_icon_tips_err"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
}
else
{
image = [[UIImage imageNamed:@"common_icon_tips_success"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
}

_errorSuccessIconImageView.sd_layout
.leftSpaceToView(_errorSuccessBackgroundView, 11)
.centerYEqualToView(_errorSuccessBackgroundView)
.widthIs(image.size.width)
.heightIs(image.size.height); // 设置高度约束

//错误提示
_errorSuccessInfoLabel.sd_layout
.leftSpaceToView(_errorSuccessIconImageView, 14)
.rightSpaceToView(_errorSuccessBackgroundView, 11)
.centerYEqualToView(_errorSuccessBackgroundView)
.heightIs(36); // 设置高度约束


_hitBtn.sd_layout
.rightSpaceToView(_errorSuccessBackgroundView, 0)
.centerYEqualToView(self)
.widthIs(60) // 设置宽度约束
.heightIs(18); // 设置高度约束

_text.sd_layout
.rightSpaceToView(_hitBtn, 0)
.centerYEqualToView(self)
.widthIs(120) // 设置宽度约束
.heightIs(18); // 设置高度约束

_configBtn.sd_layout
.rightSpaceToView(_text, 0)
.centerYEqualToView(self)
.widthIs(60) // 设置宽度约束
.heightIs(18); // 设置高度约束

}

#pragma mark - 滑动手势 各种状态
//滑动手势
-(void)painAction:(UIPanGestureRecognizer )recognize
{
if ((nil == recognize) || (recognize.state == UIGestureRecognizerStateEnded)){
CGPoint center = _errorSuccessBackgroundView.center;
if (kScreenWidth
1/2 >= center.y)
{
self.bannerTimerCount = 0.1;
[self bannerGrogress];
}
}
}

  • (void)configAction:(UIButton *)sender;
    {

}
@end