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 メソッドからのエラーを処理したいと考えています。doNext ブロック内から rac_POST シグナルのサブスクライバーにエラーを送信することは可能ですか? ただし、サブスクライバーへのポインターがありません...同様に、キーチェーンメソッドでエラーが発生した場合でも、シグナルは引き続き送信されて完了し、呼び出し元のビューコントローラーが知る限り、ログインは成功します。これは明らかに本来の動作方法ではありません。
この状況全体を処理する他の好ましい方法はありますか? doNext ブロックの副作用が好ましくないことはわかっていますが、この場合、UserManager にこのメソッドを所有させ、独自の currentUser を設定できるようにするため、他の解決策はありません。これを新しいシグナルでラップし、代わりに next、complete、および error を明示的に送信する必要がありますか?
よろしく、ジェンス