Jes*_*sse 34 methods objective-c callback ios objective-c-blocks
我有一个回调方法,我必须工作,但我想知道如何传递值.
我有的是这个:
@interface DataAccessor : NSObject
{
void (^_completionHandler)(Account *someParameter);
}
- (void) signInAccount:(void(^)(Account *))handler;
Run Code Online (Sandbox Code Playgroud)
上面的代码有效,但我想将值传递给方法.这看起来怎么样?就像是:
- (void) signInAccount:(void(^)(Account *))handler user:(NSString *) userName pass:(NSString *) passWord;
Run Code Online (Sandbox Code Playgroud)
?
Stu*_*art 117
我不完全确定你在那里做什么 - 你的回调是一个障碍......这是故意的吗?我希望你的方法看起来像这样:
- (void)signInAccountWithUserName:(NSString *)userName password:(NSString *)password;
Run Code Online (Sandbox Code Playgroud)
如果回调的意图是在完成时执行一些额外的代码(在调用方法时指定),那么一个块将是有用的.例如,您的方法如下所示:
- (void)signInAccountWithUserName:(NSString *)userName
password:(NSString *)password
completion:(void (^)(void))completionBlock
{
// ...
// Log into the account with `userName` and `password`...
//
if (successful) {
completionBlock();
}
}
Run Code Online (Sandbox Code Playgroud)
然后像这样调用方法:
[self signInAccountWithUserName:@"Bob"
password:@"BobsPassword"
completion:^{
[self displayBalance]; // For example...
}];
Run Code Online (Sandbox Code Playgroud)
此方法调用会将用户登录到帐户中,然后在完成后立即显示余额.这显然是一个人为的例子,但希望你能得到这个想法.
如果这不是您想要的那种,那么只需使用如上所述的方法签名.
编辑(使用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);
}
Run Code Online (Sandbox Code Playgroud)
您还会看到,这一次我们在调用之前检查completionBlock参数是不是nil- 如果您希望允许在没有完成块的情况下使用该方法,这一点很重要.您可以像这样使用此方法:
[self signInAccountWithUserName:@"Bob"
password:@"BobsPassword"
completion:^(BOOL success) {
if (success) {
[self displayBalance];
} else {
// Could not log in. Display alert to user.
}
}];
Run Code Online (Sandbox Code Playgroud)
更好的是(如果你可以原谅大量的例子!),如果用户知道失败的原因是有用的,那么返回一个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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后,调用者可以使用NSError完成块中的内容来决定如何继续(最有可能向用户描述出错的地方).这种模式稍微不那么常见(虽然完全有效); 大多数NSErrors是由指针间接返回的,例如在NSFileWrappers -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).
Run Code Online (Sandbox Code Playgroud)
但是,在登录示例中,我们可能希望登录尝试需要一些时间来完成(例如登录到在线帐户),因此使用完成处理程序来传递错误是完全合理的.