我使用ReactiveCocoa和Overcoat/Mantle/AFNetworking从RESTful API中获取数据和验证用户。
这是登录视图控制器中的代码,用于管理凭据的登录按钮和文本字段:
@weakify(self);
self.loginButton.rac_command =
[[RACCommand alloc] initWithEnabled:validCredentials
signalBlock:^RACSignal *(id input) {
@strongify(self);
return [[PFUserManager sharedManager] logInUser:self.usernameTextField.text
password:self.passwordTextField.text];
}];
// Handle errors for the login command
[self.loginButton.rac_command.errors subscribeNext:^(NSError *error) {
// Present the error message
[PFErrorAlertFactory showOVCError:error];
}];
// Take care of the signal from the request
[[self.loginButton.rac_command.executionSignals flatten] subscribeNext:^(NSNumber *success) {
@strongify(self);
[self clearTextFields];
[self.flowController controllerForMainScreen]; // Transition to "logged in state"
} error:^(NSError *error) {
@strongify(self);
[self clearTextFields];
}];我在单例UserManager类上有这样的方法:
- (RACSignal *)logInUser:(NSString *)username password:(NSString *)password {
// Return a cold signal that sends next and complete when user is authenticated and error if authentication failed.
PFAPIClient *client = [[PFAPIClient alloc] initWithUsername:username password:password];
@weakify(self);
RACSignal *loginSignal = [[client rac_POST:kAuthenticationResourcePath parameters:nil] doNext:^(OVCResponse *response) {
@strongify(self);
self.currentUser = response.result;
NSError *error;
[SSKeychain setPassword:password forService:kKeychainServiceKey account:self.currentUser.username error:&error];
if (error) {
[PFErrorAlertFactory showLocalizedDescriptionOfError:error];
}
}];
return loginSignal;
}这都很好,用这个信号作为按钮的RACCommand信号。接下来,我在登录视图控制器中处理错误和已完成的事件,它工作正常。
正如您在UserManager代码中看到的那样,在doNext块中,如果Keychain方法返回一个错误,我将显示一个错误。对于这个错误处理是否属于这个类,我有点不确定。
这个错误显示为一个UIAlertView,但是这个UserManager类真的应该负责显示错误吗?
来自rac_POST信号的错误由登录视图控制器处理,我也想在这里处理来自Keychain方法的错误。是否有可能从rac_POST块内向doNext信号的用户发送错误?我错过了一个指向订户的指针.此外,如果Keychain方法中出现错误,信号仍然会发送next和complete,并且据调用视图控制器所知,登录是成功的。这显然不是它应该工作的方式。
有没有其他更好的方法来处理这件事?我知道doNext块中的副作用不是首选的,但在这种情况下,我看不到其他解决方案,因为我希望UserManager拥有这个方法,并能够设置自己的currentUser。我是否应该将其封装在一个新的信号中,并显式地发送next、complete和error?
你好,詹斯
发布于 2015-06-11 06:39:15
您可以创建SSKeychain类别:
@interface SSKeychain (RACExtension)
- (RACSignal*)rac_setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account;
@end
@implementation SSKeychain (RACExtension)
- (RACSignal*)rac_setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account
{
[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSError *error;
BOOL result = [SSKeychain setPassword:password forService:service account:account error:&error];
if (result) {
[subscriber sendNext:@(result)];
[subscriber sendCompleted];
} else {
[subscriber sendError:error];
}
}];
}
@end然后使用你的UserManager
- (RACSignal *)logInUser:(NSString *)username password:(NSString *)password
{
PFAPIClient *client = [[PFAPIClient alloc] initWithUsername:username password:password];
@weakify(self);
return [[[client rac_POST:kAuthenticationResourcePath parameters:nil]
flattenMap:^RACStream *(OVCResponse *response){
@strongify(self)
return [[SSKeychain rac_setPassword:password forService:kKeychainServiceKey account:self.currentUser.username]
mapReplace:response];
}]
doNext:^(OVCResponse *response){
@strongify(self)
self.currentUser = response.result;
}]
}https://stackoverflow.com/questions/30754490
复制相似问题