1

I have some code that makes a http call to a json based webservice. That's working fine but I tried to move the code to it's own class and I have a slight hang up. When I call the method, the main thread just continues to the next command without wait for a response from my method.

Here's some code from the main part of the program

[newcall run];
    NSLog(@"%@",[newcall status]);
    NSArray *resultarray= [newcall returndata];
    for (NSString *element in resultarray) {
        NSLog(@"%@",element);
}

My Header

#import "AFHTTPClient.h"

@interface jsoncall : AFHTTPClient
{
    NSString* Date;
    NSString* apps;
    NSString* data1;
    NSURL* url;
    NSString* Path;
    NSArray* returndata;
    NSString* status;
}

-(void) setApp: (NSString *)input;

-(void) setData: (NSString *)input;

-(void) setURL: (NSString *)input;

-(void) setPath: (NSString *)input;

-(int) run;

-(NSArray *) returndata;
-(NSString *) status;

@end

My run method

-(int) run
{
    __block int success;
    NSDictionary* jsonDictionary=[NSDictionary dictionaryWithObject: data1 forKey:@"data"];
    NSString* jsonString = [jsonDictionary JSONRepresentation];
    AFHTTPClient *httpClient=[[AFHTTPClient alloc] initWithBaseURL:url];
    NSDictionary *params =[NSDictionary dictionaryWithObjectsAndKeys:
                           apps,@"app",
                           jsonString,@"smpdata",nil];
    NSMutableURLRequest *request = [httpClient requestWithMethod:@"POST" path:Path parameters:params];

    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
                    success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
                        NSArray *dataarray=[JSON valueForKey:@"Data"];
                        status= [NSString stringWithFormat:@"%@",[JSON valueForKeyPath:@"Status"]];
                        NSLog(@"%@",status);
                        returndata= dataarray;
                        success=1;
                        NSLog(@"Success: Made it here");
                    }
                    failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error,id JSON)
                    {
                        success=0;
                        NSLog(@"Error: Made it here");
                    }
    ];

    [operation start];
    [operation waitUntilFinished];
    return success;
}
Codeguy007
  • 891
  • 1
  • 12
  • 32

1 Answers1

-1

The method I used was Asychronous and as such I would have to have chained the next set of processing by calling it from the completion block. When the final app is done, we may do that but there's also this solution.

Waiting for completion block to complete in an AFNetworking request

By switching AFJSONRequestOperation to NSURLConnection, I am able to use Sychronous Mode which means the request has to complete before the thread moves on.

NSMutableURLRequest *request = [httpClient requestWithMethod:@"POST" path:Path parameters:params];

NSURLResponse *response = nil;
NSError *error = nil;

NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

if (error) {
    NSLog(@"Error: %@",error);
}
else {
    id JSON = AFJSONDecode(data, &error);
    NSArray *dataarray=[JSON valueForKey:@"Data"];
    status= [NSString stringWithFormat:@"%@",[JSON valueForKeyPath:@"Status"]];
    NSLog(@"%@",status);
    returndata= dataarray;

}

For our needs Synchronous mode should work fine for now.

However

You should not run a Synchronous web call on an UI thread because it will block and make your UI unresponsive. That means you need to put your call to this class in it's own thread with any other code that relies on it. I believe you want to check out use of NSOperation but I'm a Objective-c noob so I won't be adding an example here.

Community
  • 1
  • 1
Codeguy007
  • 891
  • 1
  • 12
  • 32
  • -1: Blocking the main thread for a web request is not even close to acceptable, no matter what kind of app you are developing. If you are going to do that, fine, but do not post it as an answer for others to emulate. – Jody Hagins Sep 07 '12 at 22:43
  • We don't actually plan on using this on the main thread. I'm writing a piece of the code period. There will be other code to go in with it. Would you like me to wrap this in an operation just for you? Besides NSURLConnection has a 60s timeout which can be changed so I can tell the user to wait while I get the information. Also because I am writing a class to handle the json message passing, I prefer to take the thread management out of the class for my example. The Android version of the app took the Asynchronous task out of the class to. I create task and then called the class. – Codeguy007 Sep 08 '12 at 10:50
  • I hope you also voted down the original answer. I've modified my post to make it clear that class should be called by an operation because the web call itself is Synchronous. – Codeguy007 Sep 08 '12 at 10:55