Search code examples
iphoneioscocoauiactivityindicatorviewdelegation

Refactoring my code for asynchronous NSURLConnection


There are problems with using synchronous requests. The problem is that I am not really sure how to refactor the code below to use an asynchronous request to accomplish the following two tasks:

  1. Use a UIActivityIndicatorView subview to notify of active fetching;
  2. Implement a Reachability check before the connection request to ensure that there is an Internet connection and that the host is available, i.e. reachabilityWithHostName:@"wwww.mywebhostingisterrible.com".

Currently I have a Fetcher class with a +(Fetcher *)sharedFetcher singleton that is used in all of my view controllers to fetch data. Currently all data is fetched using the following code:

- (NSString *)stringWithUrl:(NSURL *)url {

    NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];

    NSData *urlData;
    NSURLResponse *response;
    NSError *error;

    urlData = [NSURLConnection sendSynchronousRequest:urlRequest
                                    returningResponse:&response
                                                error:&error];

    return [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding];

}

A method that fetches looks like this:

-(NSArray *)fetchDogFoodListing {
    NSString *urlString = [NSString stringWithFormat:@"%@query/dogFood/%@/%lli/%@/%@",self.connectionUrl,self.queryCriteria.dogFoodName,self.queryCriteria.dogFoodBrandId,self.queryCriteria.dogFoodIngredients,self.queryCriteria.dogFoodBrand];
    NSString *json = [self stringWithUrl:[NSURL URLWithString:urlString]];
    return [self.factory buildIKDogFoodArrayWithJSON:json];
}

and a call from the UIViewController in -(void)viewDidLoad looks like this:

self.dogFoods = [[IKFetcher sharedFetcher] fetchDogFoodListing];

I have thought about implementing a delegate in this situation but I am very shaky on how delegation ought to work. I'm not even sure which way it should go. Should the Fetcher have a FetcherDelegate that can notify the view controller of when it is done, so the UI can update? Should the view controller have a delegate so that the fetcher can update the view when stuff is done?

I'm sure based on my questions you can see my inexperience with delegation, so I would appreciate any help.


Solution

  • You could do something like this

    dispatch_async(queue, ^{
        NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30];
    
        NSData *urlData;
        NSURLResponse *response;
        NSError *error;
    
        urlData = [NSURLConnection sendSynchronousRequest:urlRequest
                                    returningResponse:&response
                                                error:&error];
        dispatch_async(dispatch_get_main_queue(), ^{
             //.. do stuff with data here...
        }
    }
    

    or you could just do the sendSynchronousRequest code inside a dispatch_sync if you want the connection to be synchronous, though you should really should be as asynchronous as possible.