问题
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