响应式:通知,代理,KVO
RAC是函数响应式,优点:所有业务逻辑代码在一起便于阅读
用Cocopods导入
pod 'ReactiveObjC','~>3.0.0'
导入头文件
#import
简单的例子
- (void)viewDidLoad {
[super viewDidLoad];
//创建信号
RACSubject *subject = [RACSubject subject];
//订阅信号:函数式编程思想
//创建订阅者,将Block保存到订阅者对象中,将订阅者保存到数组中
[subject subscribeNext:^(id _Nullable x) {
//回调
NSLog(@"%@",x);
}];
//发送信号
[subject sendNext:@"厉害了"];
}
1:代理 VS RAC
代理的流程:
代理:
1、定义协议
2、协议的方法
3、代理属性
4、代理属性有没有值!有没有响应我的协议方法!
外界:
1、设置代理
2、遵守协议
3、实现方法
案例:控制器页面上放一个View,View上面一个按钮,点击按钮,在控制器上接收信息
//RAC做法
//view.h中
#import
@interface CusView : UIView
@property (nonatomic,strong) RACSubject *btnClickSubject; //信号
@end
//view.m中
//懒加载
- (RACSubject *)btnClickSubject{
if (!_btnClickSubject) {
_btnClickSubject = [RACSubject subject];
}
return _btnClickSubject;
}
//点击事件
- (IBAction)btnClick:(id)sender{
[self.btnClickSubject sendNext:@""];
}
//Controller中
@interface ViewController ()
@property (weak, nonatomic) IBOutlet CusView *cusView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.cusView.btnClickSubject subscribeNext:^(id _Nullable x) {
NSLog(@"收到了:%@",x);
}];
}
@end
//下面是简化版:
自定义View中都不用写,直接在controller中监控View中的方法
//Controller中
@interface ViewController ()
@property (weak, nonatomic) IBOutlet CusView *cusView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//监听View中的方法
[[self.view rac_signalForSelector:@selector(btnClick:)] subscribeNext:^(RACTuple * _Nullable x) {
NSLog(@"收到信号了!!!");
}];
}
@end
//**************如果传值****************
//view.h中
#import
@interface CusView : UIView
@end
//view.m中
//点击事件
- (IBAction)btnClick:(id)sender{
[self send:@"嘿嘿"];
}
- (void)send:(id)objc{
}
//Controller中
@interface ViewController ()
@property (weak, nonatomic) IBOutlet CusView *cusView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//只要调用了send:方法就可以得到响应
[[self.view rac_signalForSelector:@selector(send:)] subscribeNext:^(RACTuple * _Nullable x) {
NSLog(@"收到信号了!!!%@",x);
}];
}
2:KVO VS RAC
- (void)viewDidLoad {
[super viewDidLoad];
[self.cusView addObserver:self forKeyPath:@"frame" options:(NSKeyValueObservingOptionNew) context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
}
- (void)dealloc{
[self.cusView removeObserver:self forKeyPath:@"frame"];
}
//RAC做法
//头文件
#import
- (void)viewDidLoad {
[super viewDidLoad];
[self.cusView rac_observeKeyPath:@"frame" options:(NSKeyValueObservingOptionNew) observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
//回调
}];
}
//下面是简化版:
- (void)viewDidLoad {
[super viewDidLoad];
[[self.cusView rac_valuesForKeyPath:@"frame" observer:self] subscribeNext:^(id _Nullable x) {
}];
}
3:Target VS RAC
- (void)viewDidLoad {
[super viewDidLoad];
[_btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)btnClick:(UIButton *)sender{
}
//RAC做法
- (void)viewDidLoad {
[super viewDidLoad];
[[_btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
//做一些操作
NSLog(@"%@",x);
}];
}
4:通知 VS RAC
- (void)viewDidLoad {
[super viewDidLoad];
//发送通知
[[NSNotificationCenter defaultCenter] postNotificationName: UIKeyboardWillShowNotification object:nil];
//(其他地方)接收通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(click:) name: UIKeyboardWillShowNotification object:nil];
}
- (void)click:(NSNotification *)noti{
}
//RAC做法
- (void)viewDidLoad {
[super viewDidLoad];
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
NSLog(@"%@",x);
}];
}
5:监听textField VS RAC
使用代理UITextFieldDelegate
//RAC做法
- (void)viewDidLoad {
[super viewDidLoad];
[self.textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
NSLog(@"%@",x);//实时的监听textField的输入
}];
}
6:Timer VS RAC
- (void)viewDidLoad {
[super viewDidLoad];
NSThread *thread = [[NSThread alloc] initWithBlock:^{
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];//死循环
}];
[thread start];
}
- (void)timerMethod{
NSLog(@"%@",[NSThread currentThread]);
}
//RAC做法
- (void)viewDidLoad {
//基于GCD,效率高
//[RACScheduler scheduler]在子线程
//[RACScheduler mainThreadScheduler]在主线程
[[RACSignal interval:1.0 onScheduler:[RACScheduler scheduler]] subscribeNext:^(NSDate * _Nullable x) {
NSLog(@"%@----%@",x,[NSThread currentThread]);
}];
}
小例子:按钮倒计时⏳
@interface ViewController ()
@property (nonatomic,strong) UIButton *btn;
@property (nonatomic,assign) int time;
@property (nonatomic,strong) RACDisposable *disposable;
@end
@implementation ViewController
- (void)sendClick:(id)sender{
//改变状态
self.btn.enabled = NO;
//设置倒计时
self.time = 10;
//每一秒
_disposable = [[RACSignal interval:1.0 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSDate * _Nullable x) {
NSLog(@"%@",[NSThread currentThread]);
//设置按钮文字
NSString *btnText = self.time > 0 ? [NSString stringWithFormat:@"请骚等%d秒",self.time] : @"重新发送";
[self.btn setTitle:btnText forState:self.time > 0 ? UIControlStateDisabled : UIControlStateNormal];
if (self.time > 0) {
self.btn.enabled = NO;
}else{
self.btn.enabled = YES;
[_disposable dispose];//取消订阅
}
//减去时间
self.time --;
}];
}
@end
宏
//用于给某个对象的某个属性绑定。(textF的文本付给label的text属性)
RAC(_label,text) = _textF.rac_textSignal;
// [self.textField.rac_textSignal subscribeNext:^(id x) {
// self.label.text = x;
// }];
//观察self.view的frame,当frame变化的时候会响应
[RACObserve(self.view, frame) subscribeNext:^(id _Nullable x) {
}];
//RACTuplePack:把数据包装成RACTuple(元组类)
// 把参数中的数据包装成元组
RACTuple *tuple = RACTuplePack(@10,@20);
//RACTupleUnpack:把RACTuple(元组类)解包成对应的数据。
// 把参数中的数据包装成元组
RACTuple *tuple = RACTuplePack(@"xmg",@20);
// 解包元组,会把元组的值,按顺序给参数里面的变量赋值
// name = @"xmg" age = @20
RACTupleUnpack(NSString *name,NSNumber *age) = tuple;
关于循环引用
@weakify(self);
RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id _Nonnull subscriber) {
@strongify(self);
NSLog(@"%@",self);
return nil;
}];