Getting variable from the inside of block [duplicate]

試著忘記壹切 提交于 2019-12-11 09:15:35

问题


I'm using AFNetworking 2 to GET data from server and I need to get back the responseObject but no matter what I do i still get <null>.

Here is the method which is sending GET request to server and in response it gets NSDictionary which I want to use in another method...

- (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]);
    }];
}

If I call this method everything works fine. But when I try to make it return NSDictionary like this:

- (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;
}

I get <null> value. I know this is happening because of async but how to solve this? I've tried to pass another completion block to this method but when I call it inside another one I still cannot assign the result to the variable... Please guys, help me!


回答1:


You want to pass in a completion block that takes NSDictionary as parameter:

- (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]);
    }];
}

To use it:

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



回答2:


I'm sure the problem with async calls, threads run in parallel and you return nil before you get actual data, so easy way (not the prefect! :) ) is to make it synchronous to wait for result:

try:

- (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;
}

or better to use Michaels answer to return in completion block if you need it async, its a good way to return cached data before actual data coming.




回答3:


Try this, I dont remember how a blocks is created in my head and im not on my mac. But i think its like this.

__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]);
}];


来源:https://stackoverflow.com/questions/22919135/getting-variable-from-the-inside-of-block

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!