Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you return from an asynchronous NSURLConnection to the calling class?

I've got the following class which makes an HTTP post request asynchronously to avoid problems on the main UI thread:

@implementation DataFeeder

-(void) doLookup:(NSString *)inputValue
{
    NSString *myRequestString = [NSString stringWithFormat:@"val=%@", inputValue];
    NSMutableData *myRequestData = [ NSMutableData dataWithBytes: [ myRequestString UTF8String ] length: [ myRequestString length ] ];

    NSURL * myUrl = [NSURL URLWithString: @"http://mywebsite/results.php"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: myUrl]; 
    [request setHTTPMethod: @"POST"];
    [request setHTTPBody: myRequestData];
    [request setTimeoutInterval:10.0];

    [[NSURLConnection alloc] initWithRequest:request delegate:self];
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    responseData = [[NSMutableData alloc] init];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [responseData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    // Show error message
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    // Use responseData
    // Got all my response data here, so build up an object ready to send back
}

@end

I'm invoking the above from my ViewController using the following line of code :

MyObject * myObj = [feeder doLookup:@"SomeStaticStringForNow"];

So, this is how I understand it :

  1. The doLookup will execute the request on an asynchronous connection.
  2. When the data has been fully loaded, it will invoke connectionDidFinishLoading
  3. Once the data has finished loading, I will build up an object from the response data that I will send back to the calling controller

How can I have the calling controller listen out for this? Do I need to implement my own callback methods in the ViewController that will listen out for invocation and then stop a spinner and update the UI based on the contents of myObj ?

I'm hoping theres a really easy way that I've overlooked...

Thanks

like image 943
Jimmy Avatar asked Dec 16 '22 23:12

Jimmy


1 Answers

Yeah, you should implement your callback using the delegate pattern. That is, in my opinion, the easiest and most standard way to do it. There are other ways, as you can see in the other responses.

In your DataFeeder.h file:

@protocol DataFeederDelegate
 - (void)dataReady:(NSData*)data;
@end

@interface DataFeeder : NSObject {
 id delegate_;
}
- (id)initWithDelegate:(id<DataFeederDelegate>)delegate;
@end

In your DataFeeder.m:

@implementation DataFeeder
- (id)initWithDelegate:(id<DataFeederDelegate>)delegate {
  self = [super init];
  if(self) {
    delegate_ = delegate;
  }
  return self;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
 [delegate_ dataReady:responseData];
}
@end

You would instantiate a DataFeeder object like this:

DataFeeder *dataFeeder = [[DataFeeder alloc] initWithDelegate:self];

Of course, the calling view controller has to implement the DataFeederDelegate methods.

like image 176
Fran Sevillano Avatar answered Apr 29 '23 10:04

Fran Sevillano