1.signal
这里有个两个知识点
1.冷信号、热信号:只要订阅了当前的信号才会变成热信号
2.`subscriber sendError` 和 ‘subscriber subscribeCompleted’ 是互斥的,
就是说不能同时存在
3.‘RACDisposable disposableWithBlock’ 这个回调的block,是解除订阅的回调
- (void)normalSignalTest1 {
//1。创建信号 ,默认是冷信号,只要穿件了才会真正的去调用
RACSignal * signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@"test msg"];
// [subscriber sendCompleted];
[subscriber sendError:[NSError errorWithDomain:@"" code:-1 userInfo:@{NSLocalizedDescriptionKey:@"错误描述"}]];
return [RACDisposable disposableWithBlock:^{
NSLog(@"销毁 当前的 订阅");
}];
}];
//订阅以后才会成为一个热信号
[signal subscribeNext:^(id _Nullable x) {
NSLog(@"x = %@",x);
}];
// [signal subscribeCompleted:^{
//
// NSLog(@"信号发送成功");
// }];
[signal subscribeError:^(NSError * _Nullable error) {
NSLog(@"信号发送失败:%@",error);
}];
self.signal = signal;
}
2.RACSubject
@interface RACSubject<ValueType> : RACSignal<ValueType> <RACSubscriber>
/// Returns a new subject.
+ (instancetype)subject;
// Redeclaration of the RACSubscriber method. Made in order to specify a generic type.
- (void)sendNext:(nullable ValueType)value;
@end
RACSubject是继承与RACSignal,
并遵循< RACSubscriber >协议,
说明RACSubject 就是一个信号量,并且可以发送信号量让自己通过订阅来捕获。
这样做一个回调是很简单的
比如在第一个控制器 监听 下一个控制器(TestViewController)的点击事件
TestViewController * test = segue.destinationViewController;
test.subject = [RACSubject subject];
[test.subject subscribeNext:^(id _Nullable x) {
NSLog(@"revice message:%@",x);
}];
以及点击事件的回调
- (IBAction)clickAction:(id)sender {
if (self.subject) {
[self.subject sendNext:@"From_TestViewController"];
}
}
3.RACTuple 元组类似一个数据的包装 ,类似是Dic的封装;Sequence,就是类似一个数组的概念
NSDictionary * dic = @{@"name":@"leeDev",@"age":@(25)};
[dic.rac_sequence.signal subscribeNext:^(RACTuple *x) {
RACTupleUnpack(NSString * key,NSString * value) = x;
// NSLog(@"key = %@",x[0]);
// NSLog(@"value = %@",x[1]);
NSLog(@"key = %@",key);
NSLog(@"value = %@",value);
}];
NSArray * arr = @[@"lee",@"lee2",@"lee3"];
[arr.rac_sequence.signal subscribeNext:^(id _Nullable x) {
NSLog(@"x = %@",x);
}];
4.RACCommand (我是用一个btn事件来触发)
RACCommand * command = [[RACCommand alloc]initWithSignalBlock:^RACSignal * _Nonnull(id _Nullable input) {
//这个可以是一个btn 也可以是 一个字符串
NSLog(@"input = %@",input);
return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
for (NSInteger i = 0; i < 30; i++) {
[subscriber sendNext:[NSString stringWithFormat:@"comand_msg_%@",@(i)]];
}
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"某一次订阅执行完毕");
}];
}];
}];
self.btn.rac_command = command;
[command.executionSignals subscribeNext:^(id _Nullable x) {
[x subscribeNext:^(id _Nullable x) {
NSLog(@"x = %@",x);
}];
}];
//获取当前最新的信号
[command.executionSignals.switchToLatest subscribeNext:^(id _Nullable x) {
NSLog(@"switchToLatest_x = %@",x);
}];
//执行状态,默认开始一注册就会有个信号过来,所以可以通过skip跳过第一个信号
[[command.executing skip:1] subscribeNext:^(NSNumber * _Nullable x) {
if (x.boolValue) {
NSLog(@"正在执行");
} else {
NSLog(@"执行完毕");
}
}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[command execute:@"主动的signal"];
});
4.IOS 代理、KVO、Noti、事件状态点击 的替换
1. rac_signalForSelector需要注意
‘ test’对象里面包含‘ clickAction:’方法
可以代替代理(但是设计到同步的问题也是可以代替??,后面来研究一下)
[[test rac_signalForSelector:@selector(clickAction:)] subscribeNext:^(RACTuple * _Nullable x) {
NSLog(@"x = %@",x);
}];
//2.kvo
[[self.testBtn rac_valuesAndChangesForKeyPath:@"center" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld observer:self] subscribeNext:^(RACTwoTuple<id,NSDictionary *> * _Nullable x) {
NSLog(@"x = %@",x[0]);
NSLog(@"x = %@",x[1]);
}];
[UIView animateWithDuration:2 animations:^{
CGPoint center = self.testBtn.center;
center.x += 50;
self.testBtn.center = center;
}];
//3.事件处理
[[self.testBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"x = %@",x);
}];
//4.文字的输入状态
[[self.inputTextField rac_textSignal] subscribeNext:^(NSString * _Nullable x) {
NSLog(@"x = %@",x);
}];
//5.键盘的处理 代替 通知
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
NSLog(@"x = %@",x);
}];
5.同步处理
- (void)signalSynonization {
RACSignal * signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"signal1_send"];
[subscriber sendCompleted];
});
return [RACDisposable disposableWithBlock:^{
NSLog(@"signal1该次的订阅已经结束");
}];
}];
RACSignal * signal2 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"signal2_send"];
});
return [RACDisposable disposableWithBlock:^{
NSLog(@"signal2该次的订阅已经结束");
}];
}];
//这里一定要接受多个参数,否则会崩溃
[self rac_liftSelector:@selector(uploadWithS1:S2:) withSignalsFromArray:@[signal1,signal2]];
}
- (void)uploadWithS1:(id)data S2:(id)data2 {
NSLog(@"data = %@",data);
NSLog(@"data2 = %@",data2);
}
6. 常见宏
//Target ,property
RAC(self.testLabel,text) = self.inputTextField.rac_textSignal;
[RACObserve(self.testBtn,center) subscribeNext:^(id _Nullable x) {
NSLog(@"x = %@",x);
}];
@weakify(Obj)和 @strongify(Obj)
//Tuple 打包
RACTuple *tuple = RACTuplePack(@10,@20);
//Tuple 解包
RACTupleUnpack(NSString *name,NSNumber *age) = tuple;
学习RAC 链接
http://www.jianshu.com/p/87ef6720a096
http://benbeng.leanote.com/post/ReactiveCocoaTutorial-part2
http://www.cocoachina.com/ios/20150817/13071.html
网友评论