ReactiveCocoa观察两个属性

时间:2014-07-21 22:00:43

标签: objective-c reactive-cocoa

当只观察一个属性时,以下代码可以正常工作:

[[[[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);

     }]; }

知道我做错了什么?


EDIT。电话必须这样做:

[[[[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

         }];

2 个答案:

答案 0 :(得分:4)

[[[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

           }];

答案 1 :(得分: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
}