简体   繁体   中英

ReactiveCocoa observe two properties

When observing just one property the following code works fine:

[[[[RACObserve(self, userName) ignore:nil]
           flattenMap:^(NSString *userName) {

               return [self authenticateUserWithUserName:userName andPassword:@"password"];

           }] deliverOn:RACScheduler.mainThreadScheduler]
         subscribeError:^(NSError *error) {

             // TODO: Propagate error

         }];

But when a try to observe two properties at the same time I don't get the results back:

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

          }];

Here is the rest of the code:

 @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;
     }];
      }

The client class:

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

     }]; }

Any idea of what I'm doing wrong?


EDIT. The call has to be done like this:

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

         }];
[[[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

           }];

With Swift is pretty simple

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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM