我不完全确定你在尝试做什么 - 你的回调函数是一个块...这是有意为之吗?我期望你的方法看起来像这样:
- (void)signInAccountWithUserName:(NSString *)userName password:(NSString *)password;
如果你的回调函数的意图是在完成时执行一些额外的代码(在调用该方法时指定),那么使用 block 将会很有用。例如,你的方法将会像这样:
- (void)signInAccountWithUserName:(NSString *)userName
password:(NSString *)password
completion:(void (^)(void))completionBlock
{
if (successful) {
completionBlock();
}
}
然后像这样调用该方法:
[self signInAccountWithUserName:@"Bob"
password:@"BobsPassword"
completion:^{
[self displayBalance]; // For example...
}];
这个方法调用会将用户登录到账户中,然后在完成登录后立即显示余额。显然这只是一个假设的例子,但希望你能理解。
如果这不是你想要的类型,请使用像上面那样的方法签名。
编辑(使用“successful”变量的更好示例):
更好的设计是在完成块中返回一个布尔值,描述登录的情况如何:
- (void)signInAccountWithUserName:(NSString *)userName
password:(NSString *)password
completion:(void (^)(BOOL success))completionBlock
{
if (completionBlock != nil) completionBlock(loginSuccessful);
}
你还会发现这一次我们在调用 completionBlock
参数之前先检查它不是 nil
- 如果你想让该方法无需完成块使用,这很重要。你可以这样使用该方法:
[self signInAccountWithUserName:@"Bob"
password:@"BobsPassword"
completion:^(BOOL success) {
if (success) {
[self displayBalance];
} else {
}
}];
更好的方式是(如果可以原谅大量的示例!),如果用户需要知道失败的原因,返回一个NSError
对象:
- (void)signInAccountWithUserName:(NSString *)userName
password:(NSString *)password
completion:(void (^)(NSError *error))completionBlock
{
if (loginSuccessful) {
if (completionBlock != nil) completionBlock(nil);
} else {
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
,例如在
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).
然而,在登录示例中,我们可能希望登录尝试需要一些时间才能完成(例如登录到在线账户),因此使用传递错误的完成处理程序是完全合理的。
BOOL
可能更容易,或者可能通过指针间接传递一个NSError
对象来确定登录的情况如何。 - Stuartif (successful)
是什么意思吗?我该如何定义successful
?我猜它是一个BOOL
类型的变量? - sixstatesawaysuccessful
只是一个假定的本地变量,用于描述登录是否成功。更好的解决方案可能是在完成块中返回该布尔值。我已经对答案进行了编辑,以说明这一点。 - Stuart