1

I have a method that uses AFHTTPRequestOperationManager POST to retrieve json face features:

+(Face *)getFace:(UIImage *) image
{
    __block Face *face = [[Face alloc]init];

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

    NSDictionary *parameters = @{@"selector": @"FULL"};

    NSData *imageData = UIImagePNGRepresentation(image);

    [manager POST:@"http://api.animetrics.com/v1/detect" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        [formData appendPartWithFileData: imageData name:@"image" fileName:[NSString stringWithFormat:@"file%d.png",1] mimeType:@"image/png"];
    } success:^(AFHTTPRequestOperation *operation, id responseObject) {

        NSError* error;

        face = [[Face alloc] initWithString:responseObject error:&error];

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error: %@", error);
    }];

    return face;
}

I called this method in my view controller using GCD:

dispatch_queue_t queue = dispatch_queue_create("My Queue",NULL);

dispatch_async(queue, ^{

    Face *face = [Face getFace:[UIImage imageNamed:@"image.png"]];

    dispatch_async(dispatch_get_main_queue(), ^{

        [face getPoints];

    });
});

The problem is [face getPoints] always returns null because it gets executed before getFace method finishes retrieving json object. I think that's because AFNetworking itself is using GCD. But how do I fix that? What am I missing? I am using the latest AFNetworking 2.0.

Chandranshu
  • 3,669
  • 3
  • 20
  • 37
Khaled
  • 11
  • 3

1 Answers1

0

You can do this with "continuation passing style". It might look like this:

+ (void)getFace:(UIImage *) image completion: (void (^)(Face* theFace, BOOL success, NSError* error))completion
{
    if (!completion)
        return; // If you don't care about the result, why should we do anything?

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

    NSDictionary *parameters = @{@"selector": @"FULL"};

    NSData *imageData = UIImagePNGRepresentation(image);

    [manager POST:@"http://api.animetrics.com/v1/detect" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        [formData appendPartWithFileData: imageData name:@"image" fileName:[NSString stringWithFormat:@"file%d.png",1] mimeType:@"image/png"];
    } success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSError* error = nil;
        Face* face = [[Face alloc] initWithString:responseObject error:&error];
        completion(face, nil != face, error);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        completion(nil, NO, error);
    }];
}

Then to use that, you would do this:

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    [[self class] getFace: [UIImage imageNamed:@"image.png"] completion:^(Face* theFace, BOOL success, NSError* error) {

        if (success)
        {
            dispatch_async(dispatch_get_main_queue(), ^{
                [theFace getPoints];
            });
        }
        else
        {
            NSLog(@"error: %@", error);
        }
    });
});
ipmcc
  • 29,581
  • 5
  • 84
  • 147