0

So I have some code like so:

@interface RequestHandler()

@property (nonatomic) NSInteger statusCode;

@end

@implementation RequestHandler

- (bool)sendRequest:(NSString *)surveyorId withData:(NSData *)requestData
{
    [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:true];

    if (self.statusCode == 200)
    {
        return YES;
    }

    return NO;
}

Clearly the routine will carry on into the if-else statement before the request has finished. Therefore, self.statusCode is not set properly in the delegate didReceiveResponse before it is checked. What would be the best way of doing this?

I am just thinking of adding another bool property that will be set in connectionDidFinishLoading and then loop until this property is set. Once it has done that, then it will check self.statusCode. However I am thinking this will block the thread will it not? It will be no different from a sendSynchronousRequest right? Is there any way to do this without putting it into a background thread?

Kevin Lee
  • 1,104
  • 3
  • 13
  • 33

4 Answers4

1

Instead of your sendRequest:withData: method returning a BOOL indicating success/failure, it would be better for your RequestHandler to have a delegate. It could then let its delegate know about the success/failure/whatever else when the asynchronous request has finished, instead of trying to return this information from the sendRequest:withData: method (which, as you've found out, doesn't work so well).

So, you could define you delegate protocol something like this (just as an example - you might want to include some more information in these):

@protocol RequestHandlerDelegate <NSObject>

- (void)requestHandlerSuccessfullyCompletedRequest:(RequestHandler *)sender;
- (void)requestHandlerFailedToCompletedRequest:(RequestHandler *)sender;

@end

Then, give your RequestHandler a delegate property of something that conforms to this protocol:

@property (nonatomic, weak) id<RequestHandlerDelegate> delegate;

(Make sure you set something as the delegate!)

Then, when your asynchronous request completes, you can send your delegate the appropriate message, e.g.:

[self.delegate requestHandlerSuccessfullyCompletedRequest:self];

You'll need to implement the NSURLConnection delegate methods in RequestHandler (from your code, I assume you've already done that), or, if your are targeting iOS 7+, you could take a look at NSURLSession instead.

JoeFryer
  • 2,751
  • 1
  • 18
  • 23
0

You have to implement 2 delegate methods:

  1. Status code: - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

  2. Received data: - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

Example usage:

Declaration

@interface RequestHandler : NSObject <NSURLConnectionDelegate>
{
    NSMutableData *receivedData;
}

Request

- (void)sendRequest:(NSString *)surveyorId withData:(NSData *)requestData
{

  NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];

  // Apply params in http body
  if (requestData) {
      [request setHTTPBody:requestData];
  }

  [request setURL:url];
  NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
  [connection start];
} 

Delegates

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSHTTPURLResponse *responseCode = (NSHTTPURLResponse *)response;
    if ([self.delegate respondsToSelector:@selector(didReceiveResponseCode:)]) {
        [self.delegate didReceiveResponseCode:responseCode];
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    receivedData = [[NSMutableData alloc] initWithData:data];

    if ([self.delegate respondsToSelector:@selector(connectionSucceedWithData:)]) {
        [self.delegate connectionSucceedWithData:receivedData];
    }
}
Dimitris Bouzikas
  • 4,461
  • 3
  • 25
  • 33
  • Sorry, maybe I didn't make it clear but I do have these two delegate methods implemented. They work as expected but in my ```sendRequest``` method, the ```if-else``` statement executes before the delegate methods are called. – Kevin Lee Aug 07 '14 at 10:22
  • Of course this happen, because the delegates will be called when the request is finished (it is async). So this `if clause` should be placed in the delegate: `- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response` – Dimitris Bouzikas Aug 07 '14 at 10:24
  • But thes delegate method returns void. I have another class that calls this ```RequestHandler``` class that needs to know the outcome of the request. – Kevin Lee Aug 07 '14 at 10:28
  • Yes thats why you should implement your delegates `didReceiveResponseCode` in the viewController that makes the call. In those function you can replay with BOOL as return value. – Dimitris Bouzikas Aug 07 '14 at 10:31
  • Thanks very much for your help. I got it eventually. – Kevin Lee Aug 07 '14 at 13:45
0

Instead of using NSURLConnection with delegate methods you can use NSURLConnection sendAsynchronousRequest block in your code. In the example you can check connection error and compare status codes.

NSURL *URL = [NSURL URLWithString:@"http://yourURLHere.com"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *rspreportStatus, NSData *datareportStatus, NSError *e)
{

    NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)rspreportStatus;
    int code = [httpResponse statusCode];

    if (e == nil && code == 200)
    {
        // SUCCESS
    } else {
        // NOT SUCCESS
    }
}];
modusCell
  • 13,151
  • 9
  • 53
  • 80
-1

You can also check by logging this returnString.

        NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
        NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
        NSArray *arrpicResult = [returnString JSONValue];
Avinash Tag
  • 162
  • 2
  • 12
  • 1
    I am sending an asynchronous request – Kevin Lee Aug 07 '14 at 10:18
  • 1
    Ok use this [NSURLConnection sendAsynchronousRequest:request queue:nil completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSString *returnString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; }]; – Avinash Tag Aug 07 '14 at 10:33