RACSubject的底层实现和RASReplaySubject的底层实现,与RACSignal一样吗?
RACSubscriber 订阅者
用于发送信号,这是一个协议。
RACSubscriber协议有4个必须实现的方法:
- (void)sendNext:(nullable id)value;
- (void)sendError:(nullable NSError *)error;
- (void)sendCompleted;
- (void)didSubscribeWithDisposable:(RACCompoundDisposable *)disposable;
RACDisposable:用于取消订阅或者清理资源,当信号发送完成或者发送错误的时候,就会自动触发它。
RACSubject
是RACSignal的子类,因此可以充当信号,但同时它还能发送信号
使用步骤类似与RACSignal:
1.创建信号 [RACSubject subject]
2.订阅信号 - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
3.发送信号 sendNext:(id)value
但它的底层实现与RACSignal不一样。
究竟怎么不一样呢?
- subject创建时,在创建RACCompoundDisposable的同时,还创建了一个订阅者数组。
- subscribeNext调用时,除了创建订阅者,及 将nextBlock保存起来,同时会将创建的订阅者添加到订阅者数组中。
- sendNext 发送信号,会遍历subject所有的订阅者,并依次调用订阅者的nextBlock
RACSubject *subject = [RACSubject subject];
[subject subscribeNext:^(id _Nullable x) {
// block调用时刻:当信号发出新值,就会调用.
NSLog(@"第一个订阅者%@",x);
}];
[subject subscribeNext:^(id _Nullable x) {
// block调用时刻:当信号发出新值,就会调用.
NSLog(@"第二个订阅者%@",x);
}];
[subject sendNext:@"1"];
/*
源码分析
1.subject创建时,在创建RACCompoundDisposable的同时,还创建了一个订阅者数组。
- (instancetype)init {
self = [super init];
if (self == nil) return nil;
_disposable = [RACCompoundDisposable compoundDisposable];
_subscribers = [[NSMutableArray alloc] initWithCapacity:1];
return self;
}
2.subscribeNext调用时,除了创建订阅者,及 将nextBlock保存起来,同时会将创建的订阅者添加到订阅者数组中。
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
return [self subscribe:o];
}
+ (instancetype)subscriberWithNext:(void (^)(id x))next error:(void (^)(NSError *error))error completed:(void (^)(void))completed {
RACSubscriber *subscriber = [[self alloc] init];
subscriber->_next = [next copy];
subscriber->_error = [error copy];
subscriber->_completed = [completed copy];
return subscriber;
}
#pragma mark Subscription
- (RACDisposable *)subscribe:(id)subscriber {
NSCParameterAssert(subscriber != nil);
RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
NSMutableArray *subscribers = self.subscribers;
@synchronized (subscribers) {
[subscribers addObject:subscriber];
}
[disposable addDisposable:[RACDisposable disposableWithBlock:^{
@synchronized (subscribers) {
// Since newer subscribers are generally shorter-lived, search
// starting from the end of the list.
NSUInteger index = [subscribers indexOfObjectWithOptions:NSEnumerationReverse passingTest:^ BOOL (id obj, NSUInteger index, BOOL *stop) {
return obj == subscriber;
}];
if (index != NSNotFound) [subscribers removeObjectAtIndex:index];
}
}]];
return disposable;
}
3.sendNext 发送信号,会遍历subject所有的订阅者,并依次调用订阅者的nextBlock
- (void)sendNext:(id)value {
[self enumerateSubscribersUsingBlock:^(id subscriber) {
[subscriber sendNext:value];
}];
}
- (void)enumerateSubscribersUsingBlock:(void (^)(id subscriber))block {
NSArray *subscribers;
@synchronized (self.subscribers) {
subscribers = [self.subscribers copy];
}
for (id subscriber in subscribers) {
block(subscriber);
}
}
#pragma mark RACSubscriber
- (void)sendNext:(id)value {
@synchronized (self) {
void (^nextBlock)(id) = [self.next copy];
if (nextBlock == nil) return;
nextBlock(value);
}
}
*/
RACSubject可以用来代替delegate传值,类似于block传值。
#import "TwoViewController.h"
@interface TwoViewController ()
@property (weak, nonatomic) IBOutlet UIButton *backBtn;
@property (weak, nonatomic) IBOutlet UIImageView *imgV;
@property (weak, nonatomic) IBOutlet UITextField *accountTF;
@property (weak, nonatomic) IBOutlet UITextField *passwordTF;
@property (weak, nonatomic) IBOutlet UIButton *resetBtn;
@end
@implementation TwoViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
@weakify(self);
[[self.backBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
@strongify(self);
[self dismissViewControllerAnimated:YES completion:nil];
}];
RACSignal *signalA = [self.accountTF rac_textSignal];
RACSignal *signalB = [[self.passwordTF rac_textSignal] filter:^BOOL(NSString * _Nullable value) {
@strongify(self);
if (self.passwordTF.text.length > 5) {
self.passwordTF.text = [self.passwordTF.text substringToIndex:5];
}
return value.length < 5;
}];
[[RACSignal combineLatest:@[signalA, signalB] reduce:^id (NSString *account,NSString *password){
return @(account.length && password.length);
}] subscribeNext:^(NSNumber *x) {
@strongify(self);
self.resetBtn.enabled = x.integerValue;
}];
[[self.resetBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"%@",x);
@strongify(self);
if (self.delegateSubject) {
[self.delegateSubject sendNext:@[self.accountTF.text, self.passwordTF.text]];
}
[self dismissViewControllerAnimated:YES completion:nil];
}];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self.view endEditing:YES];
}
在第一个ViewController中
@weakify(self);
[[self.otherBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
@strongify(self);
TwoViewController *twoVC = [TwoViewController new];
//设置代理信号
twoVC.delegateSubject = [RACSubject subject];
[twoVC.delegateSubject subscribeNext:^(id _Nullable x) {
}];
[twoVC.delegateSubject subscribeNext:^(NSArray *x) {
NSLog(@"点击了通知按钮");
@strongify(self);
self.accountTF.text = x[0];
self.passwordTF.text = x[1];
}];
[self presentViewController:twoVC animated:YES completion:nil];
}];
RACReplaySubject
是RACSubject的子类,但它可以先订阅信号,也可以先发送信号。
如果 一个信号被订阅,就会重复播放之前的所有值,那就要先发送信号,再订阅信号。
它的底层实现又不同于父类RACSubject。???
- 创建信号,与RACSubject一样
- sendNext发送信号,不同于RACSubject.会将发送的信号添加到值接收的数组中去,然后再遍历所有的订阅者,依次调用订阅者的nextBlock
- subscribeNex订阅信号时,除创建订阅者,保存nextBlock,将订阅者添加到订阅者数组中去 这些操作之外,还会遍历replaySubject的valuesReceived数组(该数组中保存的是发送的信号值),依次将这些值再发送一次
// 1.创建信号
RACReplaySubject *replaySubject = [RACReplaySubject subject];
// 2.发送信号
[replaySubject sendNext:@1];
[replaySubject sendNext:@2];
// 3.订阅信号
[replaySubject subscribeNext:^(id x) {
NSLog(@"第一个订阅者接收到的数据%@",x);
}];
// 订阅信号
[replaySubject subscribeNext:^(id x) {
NSLog(@"第二个订阅者接收到的数据%@",x);
}];
/*
底层分析:
1.创建信号,与RACSubject一样
2.sendNext发送信号,不同于RACSubject.会将发送的信号添加到值接收的数组中去,然后再遍历所有的订阅者,依次调用订阅者的nextBlock
- (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)];
}
}
}
3.subscribeNex订阅信号时,除创建订阅者,保存nextBlock,将订阅者添加到订阅者数组中去 这些操作之外,还会遍历replaySubject的valuesReceived数组(该数组中保存的是发送的信号值),依次将这些值再发送一次
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
return [self subscribe:o];
}
+ (instancetype)subscriberWithNext:(void (^)(id x))next error:(void (^)(NSError *error))error completed:(void (^)(void))completed {
RACSubscriber *subscriber = [[self alloc] init];
subscriber->_next = [next copy];
subscriber->_error = [error copy];
subscriber->_completed = [completed copy];
return subscriber;
}
#pragma mark RACSignal
- (RACDisposable *)subscribe:(id)subscriber {
RACCompoundDisposable *compoundDisposable = [RACCompoundDisposable compoundDisposable];
RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
@synchronized (self) {
for (id value in self.valuesReceived) {
if (compoundDisposable.disposed) return;
[subscriber sendNext:(value == RACTupleNil.tupleNil ? nil : value)];
}
if (compoundDisposable.disposed) return;
if (self.hasCompleted) {
[subscriber sendCompleted];
} else if (self.hasError) {
[subscriber sendError:self.error];
} else {
RACDisposable *subscriptionDisposable = [super subscribe:subscriber];
[compoundDisposable addDisposable:subscriptionDisposable];
}
}
}];
[compoundDisposable addDisposable:schedulingDisposable];
return compoundDisposable;
}
*/