/**
* FRP(Functional Reactive Programming):函数响应式编程
* a = 2, b = 2; c = a + b; 可以得到c = 4,当b = 3时,c自动编程5;叫做响应式编程
*/
/**
* RACSignal使用 信号就是数据流
* 可以把信号想象成水龙头,只不过里面不是水,而是玻璃球(value),直径跟水管的内径一样,这样就能保证玻璃球是依次排列,不会出现并排的情况(数据都是线性处理的,不会出现并发情况)。水龙头的开关默认是关的,除非有了接收方(subscriber),才会打开。这样只要有新的玻璃球进来,就会自动传送给接收方。可以在水龙头上加一个过滤嘴(filter),不符合的不让通过,也可以加一个改动装置,把球改变成符合自己的需求(map)。也可以把多个水龙头合并成一个新的水龙头(combineLatest:reduce:),这样只要其中的一个水龙头有玻璃球出来,这个新合并的水龙头就会得到这个球。
*/
__weak typeof(self)weakSelf = self;
// 在UITextField category里面添加了属性,textfield可以直接用,当输入框选中编辑时,将给订阅者发送信号
[self.usernameTF.rac_textSignal subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
// filter 过滤信号的内容 满足条件的内容才能被返回
[[self.passwordTF.rac_textSignal filter:^BOOL(id value) {
NSString *str = value;
return str.length > 3;
}] subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
// map对信号的内容进行编辑,将编辑后的信号返回
// RAC(对象,属性) = 信号 : 将对象的属性修改为信号的内容
RAC(self.usernameTF, backgroundColor) = [self.usernameTF.rac_textSignal map:^id(NSString *value) {
return [value boolValue] ? [UIColor whiteColor] : [UIColor yellowColor];
}];
RAC(self.passwordTF, backgroundColor) = [self.passwordTF.rac_textSignal map:^id(NSString *value) {
return [value boolValue] ? [UIColor whiteColor] : [UIColor yellowColor];
}];
RACSignal *usernameSignal = [self.usernameTF.rac_textSignal map:^id(NSString *value) {
return @(value.length >= 6);
}];
RACSignal *passwordSignal = [self.passwordTF.rac_textSignal map:^id(NSString *value) {
return @(value.length >= 6);
}];
// combineLatest:@[,] 合并信号 reduce:^id(,)将信号的内容编辑,将编辑后的内容的信号返回
RACSignal *signUpActiveSignal = [RACSignal combineLatest:@[usernameSignal, passwordSignal] reduce:^id(NSNumber *usernameValid, NSNumber *passwordValid){
return @([usernameValid boolValue] && [passwordValid boolValue]);
}];
[signUpActiveSignal subscribeNext:^(NSNumber *x) {
weakSelf.loginButton.backgroundColor = [x boolValue] ? [UIColor redColor] : [UIColor blueColor];
}];
// rac_signalForControlEvents :UIControl category,触发后发送信号
// doNext:信号发送后,执行;
// flattenMap :先map 在flatten 将信号里的信号返回
[[[[self.loginButton rac_signalForControlEvents:(UIControlEventTouchUpInside)] doNext:^(id x) {
weakSelf.loginButton.backgroundColor = [UIColor yellowColor];
}] flattenMap:^id(id value) {
// return [weakSelf.viewModel loginSignalWithUsername:weakSelf.usernameTF.text andPassword:weakSelf.passwordTF.text];
// raccommand可以发送数据 execute返回信号 可以subscribeError: completed:接收
return [weakSelf.viewModel.raccommand execute:@{@"username" : @"username", @"password" : @"password"}];
}] subscribeNext:^(NSNumber *x) {
BOOL success = [x boolValue];
if (success) {
}
NSLog(@"sign in resule:%@", x);
weakSelf.loginButton.backgroundColor = [UIColor redColor];
}];
- (RACSignal *)signInSignal {
// 自定义信号,sendNext:给订阅者发送信号; sendCompleted:信号完成,信息流结束
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[RACManager signInWithUsername:self.usernameTF.text password:self.passwordTF.text complete:^(BOOL success) {
[subscriber sendNext:@(success)];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subscriber sendNext:@"false"];
});
[subscriber sendCompleted];
}];
return nil;
}];
}
- (RACSubject *)signInSignalWithSubject {
// RACSubject是racsignal的子类
RACSubject *subject = [RACSubject subject];
[RACManager signInWithUsername:self.usernameTF.text password:self.passwordTF.text complete:^(BOOL success) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subject sendNext:@(success)];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[subject sendNext:@(success)];
});
[subject sendCompleted];
});
}];
return subject;
}
viewmodel.h
- (RACCommand *)raccommand;
- (RACSignal *)loginSignalWithUsername:(NSString *)username andPassword:(NSString *)password;
viewmodel.m
self.raccommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(NSDictionary *input) {
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[self signInWithUsername:input[@"username"] password:input[@"password"] complete:^(BOOL result) {
if (result) {
[subscriber sendNext:@(result)];
} else {
[subscriber sendError:[[NSError alloc] init]];
}
}];
return nil;
}];
}];
- (RACSignal *)loginSignalWithUsername:(NSString *)username andPassword:(NSString *)password {
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[self signInWithUsername:username password:password complete:^(BOOL success) {
[subscriber sendNext:@(success)];
[subscriber sendCompleted];
}];
return nil;
}];
}
// 模拟请求数据库
- (void)signInWithUsername:(NSString *)username password:(NSString *)password complete:(void (^)(BOOL))complete {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if ([username isEqual:@"username"] && [password isEqual:@"password"]) {
complete(true);
} else {
complete(false);
}
});
}