AFNetworking 2.0 - how to pass response to another class on success from subclassed AFHTTPSessionManager

StackOverflow https://stackoverflow.com/questions/23358692

  •  11-07-2023
  •  | 
  •  

Question

Beginner ios AFNetworking 2.0 Qns: Having subclassed AFHTTPSessionManager to something like "MyAPIManager" and placed my all my API calls (GET/POST/PUT etc.) in this custom manager class, I'm having problems making use of the response on request success in another class (say class B).

I know I can refactor this and pluck out the POST call portion to class B, so that I can dump the relevant class B methods in the callback, but this would get messy, especially with multiple API calls.

I want to pass this response (e.g. the returned objectId) to another class and right now I'm just using a NSNotification which class B listens for, but this still feels a bit 'hackish' and am wondering if there is a better way to do this.

Currently in MyAPIManager : AFHTTPSessionManager:

- (void) POSTRecordJson:(NSDictionary *)json
{
[self POST:@"classes/Record/" parameters:json success:^(NSURLSessionDataTask *task, id responseObject) {
    NSLog(@"Posted JSON: %@", json.description);
    if ([responseObject isKindOfClass:[NSDictionary class]]) {
        NSLog(@"Response: %@", responseObject);
        //Notify objectId received
        [[NSNotificationCenter defaultCenter]
         postNotificationName:@"ReceivedObjectIdNotification"
         object:self
         userInfo:responseObject];
    }
} failure:^(NSURLSessionDataTask *task, NSError *error) {
    NSLog(@"Error: %@", error);
}];
}

And in Class B I've called:

MyApiManager *manager = [MyApiManager sharedInstance];
[manager POSTRecordJson:someJSONdict];
Was it helpful?

Solution

you could do 2 things.. by using a protocol/delegate or a block..

but i, personally, prefers block soo..

first make a block Datatype

typedef void(^SuccessBlock)(id success); example

and add the parameter with the block on it

- (void) POSTRecordJson:(NSDictionary *)json success:(SuccessBlock)success
{
[self POST:@"classes/Record/" parameters:json success:^(NSURLSessionDataTask *task, id responseObject) {
    NSLog(@"Posted JSON: %@", json.description);
    if ([responseObject isKindOfClass:[NSDictionary class]]) {
        NSLog(@"Response: %@", responseObject);
        //Notify objectId received
        success(responseObject);

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

and to call the new function..

MyApiManager *manager = [MyApiManager sharedInstance];
[manager POSTRecordJson:someJSONdict success:^(id result){
    NSDictionary *dictionary = (NSDictionary *)result;
    NSLog(@"response: %@",dictionary)
}];

OTHER TIPS

You would want to pass a completion block into your -POSTRecordJson: method.

For example, you would refactor your method to do the following:

- (void) POSTRecordJson:(NSDictionary *)json completion:(void(^)(BOOL success, id response, NSError *error))completion
{
    [self POST:@"classes/Record/" parameters:json success:^(NSURLSessionDataTask *task, id responseObject) {

        NSLog(@"Posted JSON: %@", json.description);
        if ([responseObject isKindOfClass:[NSDictionary class]])
        {
            NSLog(@"Response: %@", responseObject);

            if (completion) //if completion is NULL, calling it will crash your app so we always check that it is present.
            {
                completion(YES, responseObject, nil);
            }
        }
    } failure:^(NSURLSessionDataTask *task, NSError *error) {

        NSLog(@"Error: %@", error);

        if (completion)
        {
            completion(NO, nil, error);
        }

    }];
}

You could then handle this implementation like so:

//assuming `manager` and `dictionary` exist.

[manager POSTRecordJson:dictionary completion^(BOOL success, id response, NSError *error) {

    if (success)
    {
        //do something with `response`
    }
    else
    {
        //do something with `error`
    }

}];

However, if you are a beginner with AFNetworking and you want to adopt a great structure for handling web services, you should check out this excellent blog post.

You can use blocks to send the response back to the class after the response received from the server:

- (void) POSTRecordJson:(NSDictionary *)json response:(void (^)(id response, NSError *error))responseBlock
    {
    [self POST:@"classes/Record/" parameters:json success:^(NSURLSessionDataTask *task, id responseObject) {
        NSLog(@"Posted JSON: %@", json.description);
        if ([responseObject isKindOfClass:[NSDictionary class]]) {
            NSLog(@"Response: %@", responseObject);
           responseBlock(responseObject, nil);
        }
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        NSLog(@"Error: %@", error);
         responseBlock(nil, error);
    }];
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top