Objective c ReactiveCocoa有两个特性
仅观察一个属性时,以下代码可以正常工作:Objective c ReactiveCocoa有两个特性,objective-c,reactive-cocoa,Objective C,Reactive Cocoa,仅观察一个属性时,以下代码可以正常工作: [[[[RACObserve(self, userName) ignore:nil] flattenMap:^(NSString *userName) { return [self authenticateUserWithUserName:userName andPassword:@"password"]; }] deliverOn:RACScheduler.mainThrea
[[[[RACObserve(self, userName) ignore:nil]
flattenMap:^(NSString *userName) {
return [self authenticateUserWithUserName:userName andPassword:@"password"];
}] deliverOn:RACScheduler.mainThreadScheduler]
subscribeError:^(NSError *error) {
// TODO: Propagate error
}];
但是当一个科学家试图同时观察两个属性时,我没有得到结果:
[[[RACSignal
combineLatest:@[ [RACObserve(self, userName) ignore:nil],
[RACObserve(self, password) ignore:nil] ]
reduce:^(NSString *userName,
NSString *password) {
return [self authenticateUserWithUserName:userName andPassword:password];
}]deliverOn:RACScheduler.mainThreadScheduler]
subscribeError:^(NSError *error) {
// TODO: Propagate error
}];
以下是代码的其余部分:
@property (nonatomic, strong) PFPClient *client;
-(RACSignal *)authenticateUserWithUserName:(NSString *)userName andPassword:(NSString *)password {
return [[self.client authenticateUser:_userName withPassword:_password] doNext:^(PFPAccessToken *accessToken) {
self.accessToken = accessToken;
}];
}
客户端类:
-(RACSignal *)authenticateUser:(NSString *)userName withPassword:(NSString *)password {
NSString *urlString = [NSString stringWithFormat:@"https://xxxx?username=%@&password=%@", userName, password];
NSURL *url = [NSURL URLWithString:urlString];
return [[self fetchJSONFromURL:url] map:^(NSDictionary *json) {
return [MTLJSONAdapter modelOfClass:[PFPAccessToken class] fromJSONDictionary:json error:nil];
}];
}
-(RACSignal *)fetchJSONFromURL:(NSURL *)url {
NSLog(@"Fetching: %@", url.absoluteString);
// When observing two properties, next block is never executed...
return [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"Opening request...");
NSURLSessionDataTask *dataTask = [self.session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse
*response, NSError *error) {
NSLog(@"Request finished.");
if (! error) {
NSError *jsonError = nil;
id json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
if (! jsonError) {
[subscriber sendNext:json];
}
else {
[subscriber sendError:jsonError];
}
}
else {
[subscriber sendError:error];
}
[subscriber sendCompleted];
}];
[dataTask resume];
return [RACDisposable disposableWithBlock:^{
[dataTask cancel];
}];
}] doError:^(NSError *error) {
NSLog(@"%@",error);
}]; }
使用Swift非常简单
let emailSignal = self.textFieldEmail.reactive.continuousTextValues
let passwordSignal = self.textFieldPassword.reactive.continuousTextValues
emailSignal.combineLatest(with: passwordSignal).observeValues { (mail, password) in
guard let mailText = mail, let passwordText = password else {
self.buttonLogin.isEnabled = false
return
}
self.buttonLogin.isEnabled = mailText.count > 0 && passwordText.count > 0
}
使用Swift非常简单
let emailSignal = self.textFieldEmail.reactive.continuousTextValues
let passwordSignal = self.textFieldPassword.reactive.continuousTextValues
emailSignal.combineLatest(with: passwordSignal).observeValues { (mail, password) in
guard let mailText = mail, let passwordText = password else {
self.buttonLogin.isEnabled = false
return
}
self.buttonLogin.isEnabled = mailText.count > 0 && passwordText.count > 0
}
诀窍在于
展平贴图
。您可以将map
调用转换为combineTest:reduce:
调用,但是flattmap
做的更多,即在映射后进行展平。谢谢,这就是解决方案。诀窍在于flattmap
。您可以将map
调用转换为combinelateTest:reduce:
调用,但是flattmap
做的更多,即在映射后进行展平。谢谢,这就是解决方案。我将添加一些小注释。你忘了插入@weakify(self)和@strongify(self),我会添加一些小评论。您忘记插入@weakify(self)和@strongify(self)
let emailSignal = self.textFieldEmail.reactive.continuousTextValues
let passwordSignal = self.textFieldPassword.reactive.continuousTextValues
emailSignal.combineLatest(with: passwordSignal).observeValues { (mail, password) in
guard let mailText = mail, let passwordText = password else {
self.buttonLogin.isEnabled = false
return
}
self.buttonLogin.isEnabled = mailText.count > 0 && passwordText.count > 0
}