Non sono del tutto sicuro di cosa stai provando a fare lì - la tua richiamata è un blocco ... è intenzionale? Mi aspetterei il metodo a guardare qualcosa di simile:
- (void)signInAccountWithUserName:(NSString *)userName password:(NSString *)password;
Se l'intenzione del callback è quello di eseguire del codice aggiuntivo (specificato quando si chiama il metodo) al termine, poi un blocco sarebbe utile. Ad esempio, il metodo sarebbe simile a questa:
- (void)signInAccountWithUserName:(NSString *)userName
password:(NSString *)password
completion:(void (^)(void))completionBlock
{
// ...
// Log into the account with `userName` and `password`...
//
if (successful) {
completionBlock();
}
}
E quindi chiamare il metodo in questo modo:
[self signInAccountWithUserName:@"Bob"
password:@"BobsPassword"
completion:^{
[self displayBalance]; // For example...
}];
Questa chiamata metodo potrebbe accedere l'utente sul conto e poi, non appena che è completo , mostra il saldo. Questo è chiaramente un esempio forzato, ma spero che tu abbia l'idea.
Se questo non è il tipo di cosa che si intendeva, quindi utilizzare semplicemente una firma del metodo come quella sopra.
EDIT (Un esempio migliore utilizzando la variabile successful
):
Un design migliore sarebbe quella di passare un valore booleano indietro nel blocco di completamento che descrive quanto bene il login è andato:
- (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);
}
Vedrai anche che questa volta stiamo controllando che il parametro completionBlock
non sia nil
prima di chiamarlo, questo è importante se vuoi consentire il meth da utilizzare senza un blocco di completamento. Si potrebbe utilizzare questo metodo in questo modo:
[self signInAccountWithUserName:@"Bob"
password:@"BobsPassword"
completion:^(BOOL success) {
if (success) {
[self displayBalance];
} else {
// Could not log in. Display alert to user.
}
}];
Meglio ancora (! Se si può scusare le distese di esempi), se sarebbe utile per l'utente di conoscere la ragione del fallimento, restituire un oggetto 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);
}
}
il chiamante può quindi utilizzare il NSError
nel blocco di completamento per decidere come procedere (molto probabilmente, per descrivere all'utente cosa è andato storto).Questo tipo di schema è leggermente meno comune (sebbene perfettamente valido); per lo più NSError
s vengono restituiti dal puntatore indiretto, per esempio nel NSFileWrapper
s -initWithURL:options:error:
metodo:
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).
Nell'esempio di accesso, però, stiamo probabilmente aspettavamo il tentativo di accesso a prendere una certa quantità di tempo per completare (per esempio accedere a un account online), quindi è perfettamente ragionevole utilizzare un gestore di completamento che restituisce un errore.
Grazie, questo mi ha aiutato. Sì, è intenzionale. – Jesse
Probabilmente lo progetterei con 2 blocchi: successo e fallimento – vikingosegundo
@vikingosegundo: Sì, buon suggerimento. Sebbene, a seconda del contesto, potrebbe essere più facile restituire tale successo come 'BOOL', o eventualmente passare in un oggetto' NSError' da pointer-indirection per determinare quanto bene è andato l'accesso. – Stuart