4.常用用法
4.1 代替代理
JJView *view = [[JJView alloc]init];
view.backgroundColor = [UIColor yellowColor];
view.frame = CGRectMake(10, 64, 400, 500);
[self.view addSubview:view];
RACSignal *signal = [view rac_signalForSelector:@selector(didClickButton:)];
[signal subscribeNext:^(RACTuple * _Nullable x) {
NSLog(@"%@",x);
[x.rac_sequence.signal subscribeNext:^(id _Nullable x) {
if ([x isKindOfClass:[UIButton class]]) {
UIButton *btn = (UIButton *)x;
dispatch_async(dispatch_get_main_queue(), ^{
self.view.backgroundColor = btn.backgroundColor;
});
}
}];
}];
4.2 代替KVO
首先在这里我们要监听self.view
的frame
属性值的变化
JJView *view = [[JJView alloc]init];
view.backgroundColor = [UIColor yellowColor];
view.frame = CGRectMake(10, 64, 100, 100);
[self.view addSubview:view];
[view rac_observeKeyPath:@"frame" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
//回调
NSLog(@"value%@---%@",value,change);
}];
self.view = view;
touchesBegan:
方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
static int x = 50;
x++;
self.view.frame = CGRectMake(x, 64, 200, 200);
}
运行如图:
更简便的方法
JJView *view = [[JJView alloc]init];
view.backgroundColor = [UIColor yellowColor];
view.frame = CGRectMake(10, 64, 100, 100);
[self.view addSubview:view];
self.view = view;
RACSignal *signal = [view rac_valuesForKeyPath:@"frame" observer:nil];
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
运行如下图:
4.3 监听
- 监听UIButton
UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(10, 100, 100, 50)];
[self.view addSubview:btn];
[btn setBackgroundColor:[UIColor blackColor]];
[btn setTitle:@"点点" forState:UIControlStateNormal];
RACSignal *signal = [btn rac_signalForControlEvents:(UIControlEventTouchUpInside)];
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
- 监听UITextField
UITextField *textField = [[UITextField alloc]initWithFrame:CGRectMake(10, 100, 100, 50)];
textField.backgroundColor = [UIColor blueColor];
[self.view addSubview:textField];
[textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
NSLog(@"%@",x);
}];
运行如下:
4.4 代替通知
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
NSLog(@"%@",x);
}];
运行如下
4.5 代替NSTimer
在我们以往使用NSTimer 做定时循环执行的时候,
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
正常情况下运行
大家有没有遇到过,如果timerMethod
正在执行,而此时如果有UI事件的触发,比如滚动我们的屏幕,我们timerMethod
执行将会被暂停执行,一旦UI事件执行完毕,timerMethod
又会开始执行。原因是我们的NSTimer
的事件是交给Runloop
去处理,那么Runloop
在执行的时候UI模式具有最高优先权。
那要解决这种问题怎么办呢?大家可能会想到,把他放到子线程中去执行, 开启runloop
循环。
- 解决方式①——开启
runloop
循环
if (@available(iOS 10.0, *)) {
NSThread * thread = [[NSThread alloc]initWithBlock:^{
NSTimer * timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
//Runloop模式 && 多线程!!
//NSDefaultRunLoopMode 默认模式;
//UITrackingRunLoopMode UI模式:只能被UI事件唤醒!!
//NSRunLoopCommonModes 占位模式:默认&UI模式
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
//开启runloop循环
[[NSRunLoop currentRunLoop] run];
}];
[thread start];
} else {
// Fallback on earlier versions
}
- 解决方式②——GCD设置timer
//GCD设置timer
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
//GCD的事件单位是纳秒
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0);
dispatch_source_set_event_handler(timer, ^{
NSLog(@"我是timer");
NSLog(@"-----_%@",[NSThread currentThread]);
});
//启动
dispatch_resume(timer);
_timer = timer;
- 解决方式③——RAC
@interface CommonUseViewControllerr ()
@property(nonatomic,strong)RACDisposable * timerDisposable;
@end
@implementation CommonUseViewController
- (void)viewDidLoad {
[super viewDidLoad];
_timerDisposable = [[RACSignal interval:1.0 onScheduler:[RACScheduler scheduler]] subscribeNext:^(NSDate * _Nullable x) {
NSLog(@"%@",[NSThread currentThread]);
}];
}
-(void)dealloc{
//取消订阅!!
[_timerDisposable dispose];
}
@end
倒计时
@interface CommonUseViewController ()
@property(assign,nonatomic)int time;
/** */
@property(nonatomic,strong)RACDisposable * disposable;
/** */
@property(nonatomic,strong)RACSignal * signal;
@end
UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(10, 64, 100, 50)];
[btn setBackgroundColor:[UIColor blueColor]];
[self.view addSubview:btn];
[btn setTitle:@"发送验证码" forState:UIControlStateNormal];
RACSignal *signal = [btn rac_signalForControlEvents:(UIControlEventTouchUpInside)];
[signal subscribeNext:^(UIButton * btn) {
NSLog(@"%@",btn);
btn.enabled = NO;
//设置倒计时
self.time = 10;
//每一秒进来
self.signal = [RACSignal interval:1.0 onScheduler:[RACScheduler mainThreadScheduler]];
self.disposable = [self.signal subscribeNext:^(NSDate * _Nullable x) {
NSLog(@"%@",self);
//时间先减少!
_time--;
//设置文字
NSString * btnText = _time > 0 ? [NSString stringWithFormat:@"请等待%d秒",_time]
: @"重新发送";
[btn setTitle:btnText forState:_time > 0?(UIControlStateDisabled):(UIControlStateNormal)];
//设置按钮
if(_time > 0){
btn.enabled = NO;
}else{
btn.enabled = YES;
//取消订阅!!
[_disposable dispose];
}
}];
}];