2

I've implemented the AFNetworking framework, however I was trying to figure out a way of having the AFJSONRequestOperation function in a separate class and calling it from my individual view controllers.

What I've done is create a class method that takes the params in a dictionary and the webservice url. I would like this to be able to return the JSON array and the Http Code from the success block, however this is not working.

If I change the public function to have a return type and return a value at the end of the method, it returns before the success block has completed.

Any suggestions?

+ (void)RequestJSON:(NSDictionary *)params:(NSString *)webServicePath {

    NSURL *url = [NSURL URLWithString:@"http://api.website.com/"];

    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];

    NSMutableURLRequest *request = [httpClient requestWithMethod:@"POST" path:webServicePath parameters:params];
    NSLog(@"%@", request);

    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request

    success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON)
                                         {

                                           NSString *httpCode = [[JSON valueForKey:@"meta"]valueForKey:@"code"];
                                             NSLog(@"code=%@", httpCode);

                                         }

    failure:^(NSURLRequest *request , NSURLResponse *response , NSError *error , id JSON)
                                         {
                                             NSLog(@"Failed: %@",[error localizedDescription]);

                                         }];
    [operation start];

}
jcrowson
  • 4,290
  • 12
  • 54
  • 77

4 Answers4

5

From recommendation by other users, I ended up creating my own Delegate that performs two selectors, didReceiveJSON and didNotReceiveJSON in the success and failure methods.

Edit: Here's my code :)

JSONRequest.h

#import <Foundation/Foundation.h>

@class JSONRequest;

@protocol JSONRequest <NSObject>

- (void)didReceiveJSONResponse:(NSDictionary*)JSONResponse;
- (void)didNotReceiveJSONResponse;

@end

@interface JSONRequest : NSObject {

    id <JSONRequest> delegate;
}

@property (strong, nonatomic) id <JSONRequest> delegate;

- (void)RequestJSON:(NSDictionary* )params:(NSString*)webServicePath;

@end

JSONRequest.m

#import "JSONRequest.h"
#import "AFHTTPClient.h"
#import "AFJSONRequestOperation.h"

@implementation JSONRequest
@synthesize delegate;

- (void)RequestJSON:(NSDictionary *)params:(NSString *)webServicePath {

    NSURL *url = [NSURL URLWithString:@"http://api.mysite.com"];

    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];

    NSMutableURLRequest *request = [httpClient requestWithMethod:@"POST" path:webServicePath parameters:params];
    NSLog(@"%@", request);

    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request

    success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON)
                                         {
                                             NSDictionary *jsonDictionary = JSON;
                                             [delegate performSelector:@selector(didReceiveJSONResponse:) withObject:jsonDictionary];
                                         }

    failure:^(NSURLRequest *request , NSURLResponse *response , NSError *error , id JSON)
                                         {
                                             NSLog(@"Failed: %@",[error localizedDescription]);
                                             [delegate performSelector:@selector(didNotReceiveJSONResponse)];

                                         }];
    [operation start];

}

@end

jcrowson
  • 4,290
  • 12
  • 54
  • 77
  • can you make an example of usage ? how can i make this call and get the return from `didReceiveJSONResponse`? – Ricardo Binns May 10 '13 at 11:28
  • Can you please show how to use this? I tried to do something liek this: in my.h file I have JSONRequest* request; and i also set the delegate in the .h file like so . in my .m file i do something called this: request.delegate = self; and i do request RequestWithMetho and pass in the correct parameters to call the method, however this method does not want to process the method call. Can you please explain fully how you are using this file across your viewcontrollers. Please help. thank you jcrowsen – Pavan Oct 04 '13 at 03:35
0

Your AFJSONRequestOperation runs asynchronously! So it runs not on the main thread (which is the purpose of AFJSONRequestOperation i think), but your + (void)RequestJSON:(NSDictionary *)params:(NSString *)webServicePath method is executed on the main thread and is therefore immediately finished. For example, here's someone asking the same question.

Because AFJSONRequestOperation is based on NSOperation, you could add it to the mainQueu. But it's a bad idea to send as synchronous request from the main thread. But maybe just check out this workaround.

Community
  • 1
  • 1
Nenad M
  • 3,055
  • 20
  • 26
0

The function returns because it's task is just to set up the OperationQueue. Once it does that, it continues its flow as normal. Have you looked into implementing a delegate for it? you could post a message, something like JSONRequestDidComplete and pass the JSON dictionary as a parameter with it. Then you can do what you need with the dictionary in your view controller that is set up as the delegate of your requesting class.

Adam Johnson
  • 2,198
  • 1
  • 17
  • 23
0

I use a very similar setup. What I did was created a delegate that the async request could call and pass the JSON/NSDictionary back on. The other answers are right, the method will complete before the network request is done. This is good. Create a class to put your network calls in and set up a success and fail method that your view controllers implement. Those will get called when the request is done and you will benefit from not having a blocked UI.

Bill Burgess
  • 14,054
  • 6
  • 49
  • 86