【发布时间】:2014-07-21 22:00:43
【问题描述】:
仅观察一个属性时,以下代码可以正常工作:
[[[[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);
}]; }
知道我做错了什么吗?
编辑。调用必须像这样:
[[[[RACSignal
combineLatest:@[ [RACObserve(self, userName) ignore:nil],
[RACObserve(self, password) ignore:nil] ]]
flattenMap:^(RACTuple *userNameAndPassword) {
RACTupleUnpack(NSString *userName, NSString *password) = userNameAndPassword;
return [self authenticateUserWithUserName:userName andPassword:password];
}]
deliverOn:RACScheduler.mainThreadScheduler]
subscribeError:^(NSError *error) {
// TODO: Propagate error
}];
【问题讨论】:
-
诀窍在于
flattenMap。您可以将map调用转换为combineLatest:reduce:调用,但flattenMap的作用更多——即在映射后变平。 -
谢谢,这就是解决方案。
标签: objective-c reactive-cocoa