我有一个客观的C函数,如下所示:
- (BOOL)logInUser:(NSString*)user password:(NSString*)pass
{
__block BOOL ret;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/login", kBaseUrl]]];
[request addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
request.HTTPMethod = @"POST";
NSDictionary *dict = @{ @"username":user, @"password":pass };
request.HTTPBody = [[self urlEncodedStringFromDict:dict] dataUsingEncoding:NSUTF8StringEncoding];
[[self.session dataTaskWithRequest:request completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error)
{
if (error == nil) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"logIn statuscode=%ld", (long)httpResponse.statusCode);
ret = YES;
} else {
NSLog(@"logIn error=%@", error);
ret = NO;
}
}] resume];
return ret;
}
其中会话在标头中定义。我试图在块中更改ret的值,因为我在声明中有__block标识符,但它没有保留块之外的值,我认为它与块有关我将块作为参数传递的事实,但我不确定。
答案 0 :(得分:0)
是的,该块可以更改__block
变量的值,并且可以在块"之外看到更改。你很困惑,因为你从函数中返回ret
时没有看到更改,但这仅仅是因为该块还没有在那个时候运行,因为它&#39} ; s异步运行。
答案 1 :(得分:0)
对于您的任务,您无法同步返回结果,因为互联网请求总是需要时间来回复响应。因此,您应该稍微更改 logInUser 方法的签名和正文。它可能是:
- (void)logInUser:(NSString *)user
password:(NSString *)pass
completion:(void (^)(BOOL isSuccess))completion
{
// ...
[[self.session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// ...
if (completion) {
completion(YES); // or NO - depends on code above
}
}] resume];
}
用法:
- (IBAction)loginDidPress
{
// TODO: show activity indicator
UserManager *userManager = [UserManager new];
[userManager logInUser:self.userTextField.text
password:self.passwordTextField.text
completion:^(BOOL isSuccess) {
// TODO: hide activity indicator
// TODO: implement further logic based on result
}];
}
这种实现异步功能的方式现在最受欢迎。但您也可以使用委托模式和通知。