nsurlconnection asynchronous request

C.Johns picture C.Johns · Feb 15, 2012 · Viewed 11.3k times · Source

First of all the questions are failry simiple.. if you just want to see what they are skip to the bottom of this post and you will see them in bold.. for more detail then you can read the rest of this post...

I am just trying to iron out my NSURLConnection so that its working smoothly and I understand this properly. There is a profound lack of example/tutorials for Asynchronous connections on the internet or not any that I can find that explaine what is going on with any level of depth other than getting the connection up and running which after working on it seems pretty simple. Hopefully this question can full the void that I feel is out there for other users.

So, in my .h file i have imported the foundations headers and declared the methods required for the received or lack of received data (errors etc).

.h

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h> //add foundations
//.. other headers can be imported here

@interface MyViewController: UITableViewController { 

//Im not setting any delegates to access the methods because Is all happening in the same 
//place so I just use the key word 'self' when accessing the methods declared below
//I'm not sure if this is the best thing to do but I wasn't able to get my head around declaring the delegate or how it would help me with the way I have set up my request etc.

}
- (IBAction)setRequestString:(NSString *)string; //this method sets the request and connection methods

//these methods receive the response from my async nsurlconnection
- (void)receivedData:(NSData *)data;
- (void)emptyReply;
- (void)timedOut;
- (void)downloadError:(NSError *)error;

So thats my header file.. pretty simple not much explaining needed.

.m

//call setRequestString from some other method attached to a button click or something
[self setRequestString:@"rss.xml"];
//..

- (IBAction)setRequestString:(NSString *)string
{
    //Set database address
    NSMutableString *databaseURL = [[NSMutableString alloc] initWithString:@"http:www.comicbookresources/feeds/"]; // address not real jsut example

    //append the string coming in to the end of the databaseURL
    [databaseURL appendString:string];

    //prepare NSURL with newly created string
    NSURL *url = [NSURL URLWithString:databaseURL];

    //AsynchronousRequest to grab the data
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
    {
        if ([data length] > 0 && error == nil){
            [self receivedData:data];
        }else if ([data length] == 0 && error == nil){
            [self emptyReply];
        }else if (error != nil && error.code == NSURLErrorTimedOut){ //used this NSURLErrorTimedOut from foundation error responses
            [self timedOut];
        }else if (error != nil){
            [self downloadError:error];
        }
    }];
}

now set up the methods that were initialized in the .h file and called in the if statement above

- (void)receivedData:(NSData *)data
{
    NSString* newStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"%@", newStr);   //logs recived data
    //now you can see what data is coming in on your log
    //do what you want with your data here (i.e. start parsing methods
}
- (void)emptyReply
{
    //not sure what to do here yet?
}
- (void)timedOut
{
    //also not sure what to do here yet?
}
- (void)downloadError:(NSError *)error
{
    NSLog(@"%@", error);
    UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:@"Error!" message:@"A connection failure occurred." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
    [errorAlert show];
}

Cool so that pretty much the basics of what I have done right there.. now the questions I have are as follows.

Question one: Where I call NSURLConnection like so

[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
        {

What is happening here what is the ^ for is that executing that whole block (including the if statements) on a different thread or something? because it looks alot like grand central dispatch formatting but slightly different.

Question two: what should I be doing inside emptyReply & timedOut methods?

Question three: How would I incorporate caching into this? I would like to cache the responses I get back from different requests. i.e. with my setRequestString you will see there is a string input parameter, so i can request different rss feeds with the same method.. I need to figure out how to cache these responses into individual caches.. but im not sure where to start with it.

Finally If you have made it this far, thank you very much for reading my question. Hopefully with your responses we can get a pretty nice solution going here.. that other people can use for themselves and pick and choose the bits and peices they need that works for there own solution..

Anyway thank you very much for reading and I look forward to your replies.. even if they are just refrences to tutorials or examples you think might help me.. anything is good I just want to fully understand whats going on and whats a good solution.

Answer

mbh picture mbh · Feb 15, 2012
  1. Read about blocks in Apple documentation. Its new. Or you can read here
  2. You can show errors such as request timed out etc. You don't really have to handle them separately than the error one unless you have special logic.
  3. Try this for caching

    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:TIMEOUT_INTERVAL];