这是我的基本情景:
我正在创建一个简单的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
都不会被触发。
它就像错误信号丢失了一样。
我不确定我是否使用正确的reactivecocoa方法来处理成功信号和错误信号。
所以请帮助,谢谢。
如果我不清楚我的问题,也请告诉我。
答案 0 :(得分:0)
您可以使用@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
在信号内部引用Ctrl+\, Ctrl+S
以避免内存泄漏。