基本用法
RACSubject
/* 创建信号 */
RACSubject *subject = [RACSubject subject];
/* 订阅信号(通常在别的视图控制器中订阅,与代理的用法类似) */
[subject subscribeNext:^(id _Nullable x) {
NSLog(@"信号内容2:%@", x);
}];
/* 发送信号 */
[subject sendNext:@"发送信号2"];
RACSignal
// 1.创建信号
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id subscriber) {
// 3.发送信号
[subscriber sendNext:@"ws"];
// 4.取消信号,如果信号想要被取消,就必须返回一个RACDisposable
// 信号什么时候被取消:1.自动取消,当一个信号的订阅者被销毁的时候机会自动取消订阅,2.手动取消,
//block什么时候调用:一旦一个信号被取消订阅就会调用
//block作用:当信号被取消时用于清空一些资源
return [RACDisposable disposableWithBlock:^{
NSLog(@"取消订阅");
}];
}];
// 2. 订阅信号
//subscribeNext
// 把nextBlock保存到订阅者里面
// 只要订阅信号就会返回一个取消订阅信号的类
RACDisposable *disposable = [signal subscribeNext:^(id x) {
// block的调用时刻:只要信号内部发出数据就会调用这个block
NSLog(@"======%@", x);
}];
// 取消订阅
[disposable dispose];
RAC 的元祖,
跟我们 OC 的数组其实是一样的,它其实就是封装了我们 OC 的数组
/* 创建元祖 */
RACTuple *tuple = [RACTuple tupleWithObjects:@"1", @"2", @"3", @"4", @"5", nil];
/* 从别的数组中获取内容 */
RACTuple *TempTuple = [RACTuple tupleWithObjectsFromArray:@[@"a",@"b",@"c"]];
/* 利用 RAC 宏快速封装 */
RACTuple *newTuple = RACTuplePack(@"10", @"20", @"30", @"40", @"50");
NSLog(@"取元祖内容:%@---%@", tuple,tuple[0]);
NSLog(@"第一个元素:%@---%@", TempTuple,[TempTuple first]);
NSLog(@"最后一个元素:%@---%@", newTuple,[newTuple last]);
#pragma 4 遍历array和dictionary可以省去使用 for 循环来遍历
/* 遍历数组 */
NSArray *array = @[@"1", @"2", @"3", @"4", @"5"];
[array.rac_sequence.signal subscribeNext:^(id _Nullable x) {
NSLog(@"数组内容:%@", x); // x 可以是任何对象
}];
/* 遍历字典 */
NSDictionary *dictionary = @{@"key1":@"value1", @"key2":@"value2", @"key3":@"value3"};
[dictionary.rac_sequence.signal subscribeNext:^(RACTuple * _Nullable x) {
RACTupleUnpack(NSString *key, NSString *value) = x; // x 是一个元祖,这个宏能够将 key 和 value 拆开
NSLog(@"字典内容:%@:%@", key, value);
}];
// 替换数据
/* 内容操作 */
NSArray *array1 = @[@"1", @"2", @"3", @"4", @"5"];
NSArray *newArray1 = [[array1.rac_sequence map:^id _Nullable(id _Nullable value) {
NSLog(@"数组内容:%@", value);
return @"0"; // 将所有内容替换为 0
}] array];
/* 内容快速替换 */
NSArray *array2 = @[@"1", @"2", @"3", @"4", @"5"];
NSArray *newArray2 = [[array2.rac_sequence mapReplace:@"0"] array]; // 将所有内容替换为 0
NSLog(@"*****%@\n****%@",newArray1,newArray2);
文本框
textField.rac_textSignal
按钮
[getButton rac_signalForControlEvents:UIControlEventTouchUpInside]
试图
[self.topView rac_signalForSelector:@selector(loginAction)]
可代替代理
rac_signalForControlEvents: 和 rac_signalForSelector
[[view rac_signalForSelector:@selector(btnClick)] subscribeNext:^(RACTuple * _Nullable x) {
NSLog(@" view 中的按钮被点击了");
}];
宏
RAC:把一个对象的某个属性绑定一个信号,只要发出信号,就会把信号的内容给对象的属性赋值
// 给label的text属性绑定了文本框改变的信号
RAC(self.label, text) = self.textField.rac_textSignal;
RACObserveL:快速的监听某个对象的某个属性改变
[RACObserve(commodityVC.model, dataNum) subscribeNext:^(id _Nullable x) {
kStrongSelf(self)
self.clearBT.hidden = [x integerValue]==0?YES:NO;
self.eidtBT.hidden = [x integerValue]==0?YES:NO;
}];
RACTuple *tuple = RACTuplePack(@1,@2,@4);
// 宏的参数类型要和元祖中元素类型一致, 右边为要解析的元祖。
RACTupleUnpack_(NSNumber *num1, NSNumber *num2, NSNumber * num3) = tuple;// 4.元祖
// 快速包装一个元组
// 把包装的类型放在宏的参数里面,就会自动包装
NSLog(@"%@ %@ %@", num1, num2, num3);
可代替代理
rac_signalForControlEvents: 和 rac_signalForSelector
[[view rac_signalForSelector:@selector(btnClick)] subscribeNext:^(RACTuple * _Nullable x) {
NSLog(@" view 中的按钮被点击了");
}];
代替 KVO 监听
[[view rac_valuesForKeyPath:@"frame" observer:self] subscribeNext:^(id _Nullable x) {
NSLog(@"属性的改变:%@", x); // x 是监听属性的改变结果
}];
简单用宏
[RACObserve(commodityVC.model, dataNum)
Notification 可省去在 -(void)dealloc {} 中清除通知和监听通知创建方法的步骤
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
NSLog(@"%@ 键盘弹起", x); // x 是通知对象
}];
代替 NSTimer 计时
disposable = [[RACSignal interval:3.0 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSDate * _Nullable x) {
NSLog(@"当前时间:%@", x); // x 是当前的系统时
}];
信号过滤
// 一般和文本框一起用,添加过滤条件
- (void)fliter {
// 只有当文本框的内容长度大于5,才获取文本框里的内容
[[self.textField.rac_textSignal filter:^BOOL(id value) {
// value 源信号的内容
return [value length] > 5;
// 返回值 就是过滤条件。只有满足这个条件才能获取到内容
}] subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
}
//distinctUntilChanged:-- 如果当前的值跟上一次的值一样,就不会被订阅到
- (void)distinctUntilChanged {
RACSubject *subject = [RACSubject subject];
[[subject distinctUntilChanged] subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
// 发送信号
[subject sendNext:@1];
[subject sendNext:@2];
[subject sendNext:@2]; // 不会被订阅
}
// ignore: 忽略掉一些值
- (void)ignore {
//ignore:忽略一些值
//ignoreValues:表示忽略所有的值
// 1.创建信号
RACSubject *subject = [RACSubject subject];
// 2.忽略一些值
RACSignal *ignoreSignal = [subject ignore:@2]; // ignoreValues:表示忽略所有的值
// 3.订阅信号
[ignoreSignal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
// 4.发送数据
[subject sendNext:@1];
[subject sendNext:@3];
[subject sendNext:@2];
}
// 跳跃 : 如下,skip传入2 跳过前面两个值
// 实际用处: 在实际开发中比如 后台返回的数据前面几个没用,我们想跳跃过去,便可以用skip
- (void)skip {
RACSubject *subject = [RACSubject subject];
[[subject skip:1] subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
[subject sendNext:@1];
[subject sendNext:@2];
[subject sendNext:@3];
}
// take:可以屏蔽一些值,去前面几个值---这里take为2 则只拿到前两个值
- (void)take {
RACSubject *subject = [RACSubject subject];
[[subject take:1] subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
// 发送信号
[subject sendNext:@1];
[subject sendNext:@2];
[subject sendNext:@3];
}
//takeLast:和take的用法一样,不过他取的是最后的几个值,如下,则取的是最后两个值
//注意点:takeLast 一定要调用sendCompleted,告诉他发送完成了,这样才能取到最后的几个值
- (void)takeLast {
RACSubject *subject = [RACSubject subject];
[[subject takeLast:1] subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
// 发送信号
[subject sendNext:@1];
[subject sendNext:@2];
[subject sendNext:@3];
[subject sendCompleted];
}
// takeUntil:---给takeUntil传的是哪个信号,那么当这个信号发送信号或sendCompleted,就不能再接受源信号的内容了。
- (void)takeUntil {
RACSubject *subject = [RACSubject subject];
RACSubject *subject2 = [RACSubject subject];
[[subject takeUntil:subject2] subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
[subject2 subscribeNext:^(id _Nullable x) {
NSLog(@"?%@",x);
}];
// 发送信号
[subject sendNext:@1];
[subject sendNext:@2];
[subject2 sendNext:@3]; // 1
// [subject2 sendCompleted]; // 或2
[subject sendNext:@4];
[subject2 sendNext:@5];
[subject2 sendNext:@6];
[subject2 sendNext:@8];
}
映射
- (void)map {
// 创建信号
RACSubject *subject = [RACSubject subject];
// 绑定信号
RACSignal *bindSignal = [subject map:^id(id value) {
// 返回的类型就是你需要映射的值
return [NSString stringWithFormat:@"?ws:%@", value]; //这里将源信号发送的“123” 前面拼接了ws:
}];
// 订阅绑定信号
[bindSignal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
// 发送信号
[subject sendNext:@"123"];
}
UIButton *getButton = [UIButton buttonWithType:UIButtonTypeSystem];
getButton.frame = CGRectMake(50, 550, 100, 50);
getButton.backgroundColor = [UIColor whiteColor];
[getButton setTitle:@"get" forState:UIControlStateNormal];
[[getButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
RACSignal *signal = [[RMBaseSessionManager sharedInstance] HTTPRequeatHttpMed:HTTPMethodTypeGET URLStr:@"https://api.douban.com/v2/book/search" Params:@{@"q":textField.text}];
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"--------%@",x);
[getButton setTitle:@"请求成功" forState:UIControlStateNormal];
}];
[signal subscribeError:^(NSError * _Nullable error) {
NSLog(@"--------%@",error);
}];
}];
[self.view addSubview:getButton];
#pragma 7 属性/状态的实时监听
RAC(getButton, enabled) = [RACSignal combineLatest:@[textField.rac_textSignal, textField2.rac_textSignal] reduce:^id _Nullable(NSString * username, NSString * password){
return @(username.length && password.length);
}];