私はあなたが何をしようとしているかは完全にはわかりません。あなたのコールバックはブロックです...その意図的ですか?私はあなたの方法は、このような何かを見て期待:あなたのコールバックの意図は完了時に(あなたがメソッドを呼び出したときに指定された)いくつかの追加のコードを実行することです
- (void)signInAccountWithUserName:(NSString *)userName password:(NSString *)password;
場合、ブロックは有用であろう。
- (void)signInAccountWithUserName:(NSString *)userName
password:(NSString *)password
completion:(void (^)(void))completionBlock
{
// ...
// Log into the account with `userName` and `password`...
//
if (successful) {
completionBlock();
}
}
をそしてそうのようなメソッドを呼び出します:たとえば、あなたの方法は次のようになり
[self signInAccountWithUserName:@"Bob"
password:@"BobsPassword"
completion:^{
[self displayBalance]; // For example...
}];
このメソッドの呼び出しは、すぐにそれが完了すると、アカウントにユーザーをログインします、バランスを示す。これは明らかに工夫された例ですが、うまくいけばアイデアを得ることができます。
これが意図したものでない場合は、上記のようなメソッドシグネチャを使用するだけです。
EDIT(successful
変数を使用して、より良い例):
より良いデザインはログインが行ってどれだけ説明し、完了ブロックに戻っブールを渡すために、次のようになります。
- (void)signInAccountWithUserName:(NSString *)userName
password:(NSString *)password
completion:(void (^)(BOOL success))completionBlock
{
// Log into the account with `userName` and `password`...
// BOOL loginSuccessful = [LoginManager contrivedLoginMethod];
// Notice that we are passing a BOOL back to the completion block.
if (completionBlock != nil) completionBlock(loginSuccessful);
}
今回は、completionBlock
のパラメータがnil
でないことを確認しています。これは、呼び出し前には重要です使用するなし完了ブロック。あなたはそうのように、このメソッドを使用する場合があります:
[self signInAccountWithUserName:@"Bob"
password:@"BobsPassword"
completion:^(BOOL success) {
if (success) {
[self displayBalance];
} else {
// Could not log in. Display alert to user.
}
}];
まだよく(あなたが例の帯状の言い訳ことができれば!)、それはユーザーNSError
オブジェクトを返し、失敗の理由を知るために有用であろうとします。
- (void)signInAccountWithUserName:(NSString *)userName
password:(NSString *)password
completion:(void (^)(NSError *error))completionBlock
{
// Attempt to log into the account with `userName` and `password`...
if (loginSuccessful) {
// Login went ok. Call the completion block with no error object.
if (completionBlock != nil) completionBlock(nil);
} else {
// Create an error object. (N.B. `userInfo` can contain lots of handy
// things! Check out the NSError Class Reference for details...)
NSInteger errorCode;
if (passwordIncorrect) {
errorCode = kPasswordIncorrectErrorCode;
} else {
errorCode = kUnknownErrorCode;
}
NSError *error = [NSError errorWithDomain:MyLoginErrorDomain code:errorCode userInfo:nil];
if (completionBlock != nil) completionBlock(error);
}
}
呼び出し側はその後、(何が悪かったのか、ユーザーに記述するために、最も可能性が高い)続行する方法を決定するために、完了ブロックでNSError
を利用することができます。この種のパターンは(完全に有効ですが)やや一般的です。ほとんどNSError
sはNSFileWrapper
秒-initWithURL:options:error:
方法、例えば、ポインタの間接によって返されます。ログインの例で
NSError *error;
NSFileWrapper *fw = [[NSFileWrapper alloc] initWithURL:url options:0 error:&error];
// After the above method has been called, `error` is either `nil` (if all went well),
// or non-`nil` (if something went wrong).
、しかし、我々はおそらく、例えば(完了するまでにある程度の時間を取るためにログイン試行を期待していますオンラインアカウントにログインする)ので、エラーを返す完了ハンドラを使用することは完全に合理的です。
ありがとう、これは私を助けました。はい、それは意図的です。 – Jesse
私はおそらく2つのブロックでそれを設計するだろう:成功と失敗 – vikingosegundo
@vikingosegundo:はい、良い提案。コンテキストによっては、その成功を 'BOOL'として返す方が簡単かもしれません。あるいは、ポインタインダイレクションによって' NSError'オブジェクトを渡して、サインインがどれほどうまくいったのかを判断することもできます。 – Stuart