目标C:在块内定义变量

时间:2014-06-23 22:48:40

标签: asynchronous scope objective-c-blocks

我有一个客观的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标识符,但它没有保留块之外的值,我认为它与块有关我将块作为参数传递的事实,但我不确定。

2 个答案:

答案 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
    }];
}

这种实现异步功能的方式现在最受欢迎。但您也可以使用委托模式和通知。