ReactiveCocoa学习之一
ReactiveCocoa学习之一
1、ReactiveCocoa常见类
1.1、RACSiganl
RACSiganl信号类,一般表示将来有数据传递,只要有数据改变,信号内部接受到数据,就会马上发出数据。
<pre>
第一步:[RACSignal createSignal]来获得signal
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
//part 3: 进入didSubscribe,通过[subscriber sendNext:]来执行next block
[subscriber sendNext:@1];
NSLog(@"hehe");
//如果不在发送数据,最好发送信号完成
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"信号被销毁");
}];
}];
// 第二步 订阅信号,才会激活信号.
[signal subscribeNext:^(id x) {
NSLog(@"S1:-->%@",x);
}];
</pre>
<ol>
<li>[RACSignal createSignal:<#^RACDisposable *(id<RACSubscriber> subscriber)didSubscribe#>];来获得signal。调用子类RACDynamicSignal的createSignal来返回一个signal,并在signal中保存后面的 didSubscribe这个block
<li>[signal subscribeNext]先会获得一个subscriber,这个subscriber中保存了nextBlock、errorBlock、completedBlock
由于这个signal其实是RACDynamicSignal类型的,这个[self subscribe]方法会调用步骤一中保存的didSubscribe,参数就是1中的subscriber
<li>siganl的didSubscribe中调用[subscriber sendNext:@1];
sendNext底层其实就是执行subscriber的nextBlock
</ol>
<ol>
<li>RACSubscriber
<pre>@protocol RACSubscriber <NSObject></pre>
是一个协议。只要遵守这个协议,并且实现方法才能成为订阅者。通过create创建的信号,都有一个订阅者,帮助他发送数据。
<li>RACDisposable 用于取消订阅或者清理资源,当信号发送完成或者发送错误的时候,就会自动触发它。
</ol>
1.2 RACSubject
RACSubject:热信号 热信号就是在管线创建之后,不管是否有配套的工人,管线都会开始运作,可以随时根据外部条件送出数据。送出数据时,如果管线上有工人,数据被工人加工处理,如果没有工人,数据将被抛弃。 此时由于还没有订阅者,如果代码写在这里的话,数据会被抛弃。
<pre>
//创建信号
RACSubject *subject = [RACSubject subject];
//发送信号 1⃣️
[subject sendNext:@"hha"];
//订阅信号,
[subject subscribeNext:^(id x) {
NSLog(@"第一个订阅者%@",x);
}];
[subject subscribeNext:^(id x) {
NSLog(@"第二个订阅者%@",x);
}];
//发送信号 2⃣️
[subject sendNext:@"hhwrwee"];
//[subject sendNext:@"hhwrwee"]; 会调用一下方法
- (void)sendNext:(id)value {
[self enumerateSubscribersUsingBlock:^(id<RACSubscriber> subscriber) {
[subscriber sendNext:value];//(1)
}];
}
</pre>
其中:1⃣️中发送的信号没有被订阅者接收到,因为发送信号之前没有订阅者。这个数据将被抛弃
2⃣️发送的信号会被 两个订阅者都接收到。
当subject调用sendNext方法是。RACSubject就会遍历一遍自己的subcribers数组,并调用各数组元素(subscriber)准备好的sendNextBlock (1)
在调用subscribeNext时热信号RACSubject仅仅只是将subscriber加入到订阅者数组中,其它啥事不干。
3⃣️由于RACSubject是先有订阅者,在发送信息给订阅者接受,可以实现代理回调
1.3 RACReplaySubject
RACReplaySubject是RACSubject的一个子类。如果一个信号每被订阅一次,就需要把之前的值重复发送一遍,使用重复提供信号类。可以设置capacity数量来限制缓存的value的数量,即只缓充最新的几个值。
<pre>
RACReplaySubject *replaySub = [RACReplaySubject subject];
[replaySub sendNext:@1];
[replaySub sendNext:@2];
[replaySub subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[replaySub subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
ReactiveCocoa[1982:128524] 1
ReactiveCocoa[1982:128524] 2
ReactiveCocoa[1982:128524] 1
ReactiveCocoa[1982:128524] 2
- (void)sendNext:(id)value {
@synchronized (self) {
[self.valuesReceived addObject:value ?: RACTupleNil.tupleNil];
[super sendNext:value];
if (self.capacity != RACReplaySubjectUnlimitedCapacity && self.valuesReceived.count > self.capacity) {
[self.valuesReceived removeObjectsInRange:NSMakeRange(0, self.valuesReceived.count - self.capacity)];}}}
</pre>
其中:1⃣️sendNext方法时,现将value保存下来
2⃣️subscribeNext,遍历订阅者发送保存下来的所有值。
1.4 RACTuple和RACSequence
RACTuple(A tuple is an ordered collection of objects)是一个有序集合。RACSequence(Represents an immutable sequence of values)values的一个队列。
<pre>
NSArray *number = @[@1,@2,@3,@4];
//遍历数组
//1、RACSequence = number.rac_sequence得到有值得队列
//2、RACSequence转换RACSignal信号类,numbers.rac_sequence.signal
//订阅信号。遍历数组
[number.rac_sequence.signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
另外:
//得到队列中的第一个值
[number.rac_sequence head]
//得到一个队列的枚举器
[number.rac_sequence objectEnumerator]
//元组
NSDictionary *dict = @{@"name":@"xmg",@"age":@18};
[dict.rac_sequence.signal subscribeNext:^(id x) {
//元组解包 x是一个键值对 键值对解包可用于model赋值
RACTupleUnpack(NSString *key,NSString *value) = x;
NSLog(@"%@,%@",key,value);
}];
</pre>
1.5 RACCommand
A command is a signal triggered in response to some actionRAC中用于处理事件的类,可以把事件如何处理,事件中的数据如何传递,包装到这个类中,他可以很方便的监控事件的执行过程。
<pre>
//1.创建命令 initWithSignalBlock:(RACSignal * (^)(id input))signalBlock
//2.在signalBlock中,创建RACSignal,并且作为signalBlock的返回值
//3.执行命令 - (RACSignal *)execute:(id)input
RACCommand *command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
return [NetWorkingModel networkingWithParams:nil url:@"https://www.baidu.com"];
}];
self.command = command;
[command.executionSignals subscribeNext:^(RACSignal *name) {
[name subscribeNext:^(id x) {
NSLog(@"%@",x); //这里
}];
}];
//执行命令 不过没有这行代码command不能执行
[self.command execute:nil];
</pre>
//网络请求的一个类
<pre>
+(RACSignal *)networkingWithParams:(id)params url:(NSString *)url{
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
[manager setResponseSerializer:[AFHTTPResponseSerializer serializer]];
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"GET" URLString:url parameters:params error:nil];
NSURLSessionTask *task = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
NSString *dataString =[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
[subscriber sendNext:dataString];
[subscriber sendCompleted];
}];
[task resume];
return [RACDisposable disposableWithBlock:^{
NSLog(@"清号被销毁");
}];
}];
return signal;
}</pre>
1.6RACMulticastConnection
A multicast connection encapsulates the idea of sharing one subscription to a signal to many subscribers.利用热信号可以有多个订阅者,是一对多,信号可以与订阅者共享信息。来限制重复订阅
<pre>
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
//发送信号
NSLog(@"%d",++i);
[subscriber sendNext:@(i)];
NSLog(@"hehe");
//如果不在发送数据,最好发送信号完成
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
NSLog(@"信号被销毁");
}];
}];
RACMulticastConnection *connect = [signal publish];
//订阅一信号和订阅二信号接受到的信息是一样的
[connect.signal subscribeNext:^(id x) {
NSLog(@"%@--->订阅一信号",x);
}];
[connect.signal subscribeNext:^(id x) {
NSLog(@"%@---->订阅二信号",x);
}];
[connect connect];
</pre>
<pre>
/- (RACMulticastConnection *)publish {
RACSubject *subject = [[RACSubject subject] setNameWithFormat:@"[%@] -publish", self.name];
RACMulticastConnection *connection = [self multicast:subject];
return connection;
}
</pre>
<pre>
/- (RACDisposable *)connect {
BOOL shouldConnect = OSAtomicCompareAndSwap32Barrier(0, 1, &_hasConnected);
if (shouldConnect) {self.serialDisposable.disposable = [self.sourceSignal subscribe:_signal];
}
return self.serialDisposable;
}
</pre>
其中[signal publish]可知这里生成了一个RACSubject热信号。connect.sourceSignal -> RACSignal(原始信号) connect.signal -> RACSubject。后面操作的都是RACSubject信号
[connect connect];连接之后可知原始信号被RACSubject订阅了。就是subscriber
subscribeNext:方法的调用实际上是RACSubject调用起subscribeNext。
subscriber会向所有订阅者发送信号。