在Objective C中创建嵌套回调的最佳方法

时间:2014-01-22 12:49:34

标签: objective-c objective-c-blocks

我有一个处理与外部API交互的类,我正在尝试找出将它们分解为descreat块的最佳方法。

目前,它看起来像这样:

- (BOOL) testCredentialsWithUsername:(NSString *)username password:(NSString *)password {
    acUsername = username;
    acPassword = password;
    [self loadLoginPage];
    return YES;
}

- (void)loadLoginPage {
    [NSURLConnection sendAsynchronousRequest:...
                           completionHandler:^(...) {
                               [self logIntoMyAPI:response];
                           }];
}

- (void)logIntoMyAPI:(NSURLResponse *)response {
    [NSURLConnection sendAsynchronousRequest:...
                           completionHandler:^(...) {
                               [self recieveLoginResponse:response data:data];
                           }];
}

- (void)recieveLoginResponse:(NSURLResponse *) response data:(NSData *)data {
    if (...) {
        NSLog(@"Logged into MyAPI!");
    } else if (...) {
        NSLog(@"Invalid username or password");
    } else if (...) {
        NSLog(@"Locked account");
    } else {
        NSLog(@"An unexpected error");
    }
}

基本上,我想从我的View Controller中调用testCredtionalsWithUsername:password:,并且可能使用成功/失败块,知道结果。

如果不将回调与测试testCredtionalsWithUsername:password:方法联系起来,最好的方法是什么?

2 个答案:

答案 0 :(得分:1)

在得到测试结果之前,您需要等待服务器响应,因此从testCredentialsWithUsername:password中返回BOOL没有任何意义。似乎。

一个优雅的解决方案是拥有一个在你有答案时被调用的completionBlock。像这样:

- (void) testCredentialsWithUsername:(NSString *)username password:(NSString *)password completion:(void (^)(BOOL success, NSError *error))completion {
    acUsername = username;
    acPassword = password;
    _validationCompletion = completion; // Save this as an instance variable
    [self loadLoginPage];
}

从服务器获得结果时:

- (void)recieveLoginResponse:(NSURLResponse *) response data:(NSData *)data {
    BOOL success = data != nil; //or whatever you criteria is.

    if (_completion != nil) {

        NSError = success ? nil : [NSError new]; // create an appropriate error object

        _completion(success, error)
        _completion = nil;
    }
}

答案 1 :(得分:0)

您可以将成功阻止和失败阻止的两个属性添加到该类,并在请求完成时调用它。在视图控制器中分配此类的实例并将两个块传递给此参数。 您还可以将initWithSuccessBlock:failureBlock:方法添加到该类,并在视图控制器中初始化此类时调用此方法。

希望得到这个帮助。