2016-03-15 5 views
0

Вот мой основной сценарий:При помощи кнопки Войти Reactivecocoa срабатывает только один раз

Я делаю простой login рамки, так что я получил два text field, один для пользователя, а другой для пароля, и конечно Логин button.

Теперь я связываю их с RACSignal как это:

RACSignal *validPasswordSignal = [passwordTextField.rac_textSignal map:^id(NSString *text) 
{ 
    return @([self isPasswordValid:text]); 
}]; 

RACSignal *validUsernameSignal = [usernameTextField.rac_textSignal map:^id(NSString *text) 
{ 
    return @([self isUsernameValid:text]); 
}]; 

и объединить два сигнала (имя пользователя и пароль) в один, как это:

RACSignal *submitActiveSignal = [RACSignal combineLatest:@[validpasswordSignal, validUsernameSignal] reduce:^id(NSNumber *validPW, NSNumber *validUN) 
{ 
    return @(validPW.boolValue && validUN.boolValue); 
}]; 

Конечно, мне нужен метод, чтобы представить сигналы для имени пользователя и пароля с запросом на сервер, поэтому у меня оно выглядит следующим образом:

-(RACSignal *)submitSignal 
{ 
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) 
    { 
     [[[RequestClass alloc] init] requestWithUsername:_usernameTextField.text.trim password:_passwordTextField.text.trim completionHandler:^(MyResult *results, NSURLResponse *response, NSError *error) 
     { 
      if (!error) 
      { 
       if (results.code == 0) 
       { 
        [subscriber sendNext:@(YES)]; 
        [subscriber sendCompleted]; 
       } 
       else 
       { 
        NSError *invalidError = [NSError errorWithDomain:MyErrorDomain code:MyErrorInvalidSigniture userInfo:@{@"NSLocalizedDescription": results.message}]; 
        [subscriber sendError:invalidError]; 
       } 
      } 
      else 
      { 
       [subscriber sendError:error]; 
      } 
     }]; 
     return nil; 
    }]; 
} 

Тогда мне нужно, чтобы моя кнопка Войти поймать сигнал от абонента sendNext и sendError, так что я сделал это так:

//subscribeNext 
[[[[_submitButton rac_signalForControlEvents:UIControlEventTouchUpInside] 
doNext:^(id x) 
{ 
    _submitButton.enabled = NO; 
}] 
flattenMap:^RACStream *(id value) 
{ 
    return [self submitSignal]; 
}] 
subscribeNext:^(NSNumber *signal) 
{ 
    _submitButton.enabled = YES; 
    BOOL success = signal.boolValue; 
    if (success) 
    { 
     [self successCallback]; 
    } 
    else 
    { 
     //do sth 
    } 
}]; 

//subscribeError 
[[[[_submitButton rac_signalForControlEvents:UIControlEventTouchUpInside] 
doNext:^(id x) 
{ 
    _submitButton.enabled = NO; 
}] 
flattenMap:^RACStream *(id value) 
{ 
    return [self submitSignal]; 
}] 
subscribeError:^(NSError *error) 
{ 
    [self failureCallbackWithError:error]; 
}]; 

Выше reactivecocoa код, который я написал для моей процедуры авторизации. Когда пароль и имя пользователя были правильными, сигнал перейдет в блок ответа sendNext: subscribeNext, , но проблема в том, что учетные данные были неверными, а ошибка с сервером была возвращена, ни sendError, ни subscribeError не будут запущены.

Это как сигнал ошибки был потерян или что-то в этом роде.

Я не уверен, что я использую правильные методы реакции, чтобы обрабатывать сигнал успеха и сигнал ошибки.

Так что, пожалуйста, помогите, спасибо.

Также, пожалуйста, дайте мне знать, если я не буду разбираться в моем вопросе.

+0

Я не знаю, устранит ли это проблему, но вы не должны подписываться на событие касания кнопки дважды - вы будете отправлять два запроса каждый раз, когда он прослушивается. Используйте 'subscribeNext: error' для обработки как успеха, так и неудачи в одной подписке. –

+0

@PatrickBacon Я пробовал свой путь, но все еще не работал.Я нажал кнопку один раз, и это вызвало либо subscribeNext-блок, либо блок ошибок, который хорош; но когда я нажал кнопку во второй раз, ничего не произошло. В методе 'trigger' я помещаю' [абонент sendNext: @ (YES)]; [абонент sendCompleted] 'и' [абонент sendError: ошибка] '. Не могли бы вы взглянуть и помочь мне? – Boris

+0

Убедитесь, что вы повторно включили кнопку в обоих случаях успеха ('subscribeNext:') и ошибки ('error:'). Вероятно, вы также должны добавить 'deliverOnMainThread' после' flattenMap', чтобы убедиться, что изменения в пользовательском интерфейсе происходят в основном потоке. –

ответ

0

Вы можете использовать RACCommand и он будет заботиться о много это для вас:

@weakify(self) 
RACCommand *submitCommand = 
    [[RACCommand alloc] initWithEnabled:submitActiveSignal signalBlock:^RACSignal *(id input) { 
     @strongify(self) 
     return [[self submitSignal] 
      doCompleted:^{ 
       @strongify(self) 
       [self successCallback]; 
      }]; 
    }]; 

_submitButton.rac_command = submitCommand; 

Предоставляя submitActiveSignal как initWithEnabled: аргумента кнопки автоматически включается/выключается на основе значения излучаемой от этого сигнала.

Для обработки ошибок RACCommand имеет специальный сигнал errors, который отправляет каждую ошибку, возникающую в команде. Вы можете подписаться на errors сигнала для обработки всех ошибок, которые возникают в результате ваш сигнал возвращается внутри команды:

[[submitCommand.errors 
    takeUntil:self.rac_willDeallocSignal] 
    subscribeNext:^(NSError *error) { 
     @strongify(self) 
     [self failureCallbackWithError:error]; 
    }]; 

И не забудьте @weakify/@strongify ссылки на self внутри сигналов, чтобы избежать утечек памяти.

+0

Спасибо за ваш ответ, да, я действительно знаю об этом. Но я пытаюсь выяснить, какая проблема существует на моем пути, чтобы я мог реально понять механизм RAC. – Boris

 Смежные вопросы

  • Нет связанных вопросов^_^