Dan Brooking
Dan Brooking

Reputation: 134

How to get variables out of a block in iOS

I have the following code:

__block NSDictionary *results;

if (username.length != 0 && password.length != 0) {
    NSMutableDictionary* params =[NSMutableDictionary dictionaryWithObjectsAndKeys:
                                  @"login", @"command",
                                  username, @"username",
                                  password, @"password",
                                  nil];

    [[API sharedInstance] commandWithParams:params onCompletion:^(NSDictionary *json) {
        for (id key in json) {

            NSLog(@"key: %@, value: %@", key, [json objectForKey:key]);
        }

        results = json;
    }];
}
for (id key in results) {

    NSLog(@"key: %@, value: %@", key, [results objectForKey:key]);

}

This some code from a tutorial that I'm trying to play with to figure some things out. In the tutorial, there was a lot of code done in the 'on completion' part and I'd like to just have it return the NSDictionary so the calling code can handle the result itself.

The problem I'm having is that results is not being set. The first NSLog for loop prints output but the 2nd one does not. What am I missing?

Upvotes: 1

Views: 703

Answers (3)

Jody Hagins
Jody Hagins

Reputation: 28349

Usually, a completion handler indicates an asynchronous request. In that case, the code in the commandWithParams:onCompletion: method will not have yet run when the code after it executes.

So, you are looking at the results object, but the completion handler has not yet run to set its value, so it's still nil.

Upvotes: 1

user529758
user529758

Reputation:

You're missing understaning of asynch operations. The completion block is not invoked until the operation which you initiated has been completed. However, the NSLog statement is executed immediately after the message send to [API sharedInstance] - and results is nil then.

Upvotes: 2

Jack Lawrence
Jack Lawrence

Reputation: 10772

The problem is most likely that your commandWithParams:onCompletion: method is asynchronous. That is, it is dispatched onto another thread.

I'll assume this is a network call since this is what it looks like, but this applies to any async method. Basically it's downloading your data in the background so that you don't freeze up the app.

So what does this mean for your code? Well, you create an uninitialized pointer to an NSDictionary. Then you ask your API class's shared instance to dispatch a network request for you. Then immediately after the request is dispatched, most likely before the network request/long running process finishes, the next line of code is executed which happens to be your for loop.

Upvotes: 0

Related Questions