从块内部获取变量

时间:2014-04-07 17:26:41

标签: ios objective-c afnetworking objective-c-blocks afnetworking-2

我正在使用AFNetworking 2从服务器获取数据,我需要取回responseObject,但无论我做什么,我仍然会得到<null>

以下是向服务器发送GET请求的方法,作为响应,它获取NSDictionary我想在另一种方法中使用...

- (void)getCurrentVersionsForTimetableWithID:(NSString *)timetableID
{
    [[AFHTTPRequestOperationManager manager] GET:[NSString stringWithFormat:VERSIONS, timetableID] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        // Here I want to get responseObject
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Couldn't get current versions: %@", [error localizedDescription]);
    }];
}

如果我称这种方法一切正常。但是当我试图让它像这样返回NSDictionary时:

- (NSDictionary *)getCurrentVersionsForTimetableWithID:(NSString *)timetableID
{
    __block NSDictionary *currentVersions;

    [[AFHTTPRequestOperationManager manager] GET:[NSString stringWithFormat:VERSIONS, timetableID] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        currentVersions = responseObject;
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Couldn't get current versions: %@", [error localizedDescription]);
    }];

    return currentVersions;
}

我得到<null>值。我知道这是因为异步但是如何解决这个问题?我试图将另一个完成块传递给这个方法但是当我在另一个中调用它时,我仍然无法将结果分配给变量...请大家帮助我!

3 个答案:

答案 0 :(得分:3)

您希望传入一个以NSDictionary作为参数的完成块:

- (void)getCurrentVersionsForTimetableWithID:(NSString *)timetableID completion:(void (^)(NSDictionary* currentVersions))completion
{
    [[AFHTTPRequestOperationManager manager] GET:[NSString stringWithFormat:VERSIONS, timetableID] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        currentVersions = responseObject;

        if(completion){
            completion(currentVersions);
        }
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Couldn't get current versions: %@", [error localizedDescription]);
    }];
}

使用它:

[self getCurrentVersionsForTimetableWithID:@"someId" 
                                completion:^(NSDictionary* currentVersions){
                                    // Do something with currentVersions
                                }];

答案 1 :(得分:3)

我确定异步调用的问题,线程并行运行,并且在获得实际数据之前返回nil,所以简单的方法(不是完美!:))是让它同步等待结果:

尝试:

- (NSDictionary *)getCurrentVersionsForTimetableWithID:(NSString *)timetableID
{
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);

    __block NSDictionary *currentVersions;

    [[AFHTTPRequestOperationManager manager] GET:[NSString stringWithFormat:VERSIONS, timetableID] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        currentVersions = responseObject;
        dispatch_semaphore_signal(sema);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Couldn't get current versions: %@", [error localizedDescription]);
    }];

    while (dispatch_semaphore_wait(sema, DISPATCH_TIME_NOW))
    {
        [[NSRunLoop currentRunLoop]
         runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0]];
    }

    return currentVersions;
}

或者更好地使用Michaels答案在完成块中返回如果你需要异步,它是在实际数据到来之前返回缓存数据的好方法。

答案 2 :(得分:0)

试试这个,我不记得在我的头脑中是如何创建一个块而我不在我的mac上。但我认为它是这样的。

__block NSDictionary *currentVersions;

void (^success)(AFHTTPRequestOperation, id) = ^(AFHTTPRequestOperation *operation, id responseObject) {

    currentVersions = responseObject;
}

[[AFHTTPRequestOperationManager manager] GET:[NSString stringWithFormat:VERSIONS, timetableID] parameters:nil success:success
 failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Couldn't get current versions: %@", [error localizedDescription]);
}];