iPhone Application Development – Networking

Kanya Srinisavan
This entry is part 8 of 10 in the series iPhone Application Development

iPhone Application Development

Fetching data over network is yet another important concept to become familiar with in the process of learning iOS application development.

There are two basic APIs that help us in fetching the data over network either synchronously or asynchronously: NSURLConnection and NSURLSession.

The latter was introduced as part of iOS7 SDK with additional features. There are many libraries that are built on top of these APIs.

In this tutorial we will concentrate on these two APIs.

NSURLConnection

The ‘NSURLRequest’ class helps in creating a request to the specified URL. It specifies the target URL and the cache policy that should be adopted while making the URL request. The HTTP request type, its header fields and post data can also be specified. So, we should create an instance of NSURLRequest with the required request information.

This request object should be passed to initialize ‘NSURLConnection’ object and fire the request.

The connection delegate should also be mentioned.

Asynchronous Connection

Sample GET Request

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://samplewebservice.com?x=1&y=2"]];
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

Sample Post Request with HTTP Headers

    NSMutableURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://samplewebservice.com"]];
    request.HTTPMethod = @"POST";
    [request setValue:@"text/plain" forHTTPHeaderField:@"Content-Type"];
    NSString *str = @"Post data";
    NSData *postData = [str dataUsingEncoding:NSUTF8StringEncoding];
    request.HTTPBody = postData;
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

Sample Request with cache Policy

    NSMutableURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://samplewebservice.com"]
                                                    cachePolicy: NSURLRequestReloadIgnoringCacheData
                                                timeoutInterval:20.0];
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

After the request is triggered we should implement the NSURLConnection delegate methods to receive the response data.

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    
  //Declare a NSMutableData variable 'responseData' to hold the response from the server.
  //Initialize or reset the 'responseData' variable here.
    _responseData = [[NSMutableData alloc] init];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    // Append the data that we receive to the 'responseData' variable
    [self.responseData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
  //The response data is fully received.
  //Parsing can be done here
        NSString *strResponse = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding];
    NSLog(@"Response %@",strResponse);
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    // The request has failed due to some error
    NSLog(@"Error %@",[error description]);

}

There is one simple API, which could be used to trigger an asynchronous request.

    [NSURLConnection sendAsynchronousRequest:request
                                       queue:[NSOperationQueue mainQueue]
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                               
                           //Parse the data here
                           
                           }];

This is how we should trigger and handle an asynchronous URL connection.

Synchronous Connection:

The ‘sendSynchronousRequest’ method of the ‘NSURLConnection’ class is used to make a synchronous call to the server.

    NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://samplewebservice.com"]];
    NSURLResponse * response = nil;
    NSError * error = nil;
    NSData * responsedata = [NSURLConnection sendSynchronousRequest:request
                                          returningResponse:&response
                                                      error:&error];
    
    if (error == nil)
    {
        // Parse response data here
    }

The response and the error variables are passed as arguments to the method. The response variable will be populated with the raw response if the connection is established successfully and the response is received. The error variable will be populated with the error details if the response data cannot be received.

We should check if the error value is nil before we proceed with data parsing.

NSURLSession

With NSURLSession, we can configure cache, cookie and credential policies for each session rather than sharing it across the application. The NSURLSessionConfiguration object helps in specifying these policies and NSURLSession objects are instantiated with these configuration objects.

The NSURLSessionConfiguration API comes with three configuration settings.

Default Session: Configuration that uses global or shared cookie, cache and credential storage objects. Behaviour is similar to NSURLConnection.
Ephemeral Session: Private Session Configuration that does not persist cookie, cache and credential storage objects. As the name indicates, the configuration settings are short living and are deleted when the session is invalidated.
Background session: Similar to default session but upload or download of data can be performed even when the application is in suspended state.

The actual upload or download functions in a session is done with the help of NSURLSessionTask objects.

There are three types of session tasks

Data Tasks: Data is sent and received in the form of NSData objects
Download Tasks: Data is received in the form of file
Upload Tasks: Data is usually sent in the form of file.

Tasks can be created with completion handlers or delegates.

Follow the steps below while creating a session

  1. Create a NSURLSessionConfiguration object. (Default/Ephemeral/Background)
  2. Set cache, protocol, cookie or credential policies and additional configuration settings with the help of the session configuration object created
  3. Create a NSURLSession object
  4. Create a NSURLSessionTask object (Data/Download/Upload)
  5. Implement the completion handler or the delegate methods

Sample Data task with Completion handler

Read the inline comments and try to understand the sample code given below

    // Create a default session configuration object
    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    //Set policies and other session configuration parameters if required
    [sessionConfig setRequestCachePolicy:NSURLRequestReloadIgnoringCacheData];
    
    //Create a session with the configuration object
    //Set delegate to nil if you are going to use completion handler
    //Set the queue for the completion handlers
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:nil delegateQueue:[NSOperationQueue mainQueue]];
    
    //Create a NSURLRequest object with the webservice URL
    NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://samplewebservice.com"]];
    //Create a data task object with the session and the request object
    // Implement the completion handler that should be triggered at the end of the request
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if(error == nil)
        {
            NSString *strResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSLog(@"Response %@",strResponse);
        }
        
    }];
    
    //All the session tasks will be in the suspended state. //Call resume method on the tasks to trigger the request
    [dataTask resume];

Sample data task with delegates

Request Initiation

    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    [sessionConfig setRequestCachePolicy:NSURLRequestReloadIgnoringCacheData];
    
    //Specify the custom delegate when creating the session
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSURL *url = [NSURL URLWithString: @"http://www.example.com/"];
    NSURLSessionDataTask *dataTask = [session dataTaskWithURL: url];
    [dataTask resume];

Data Task Delegate Methods

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
    //handle data here
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    //Called when the data transfer is complete
    //Client side errors are indicated with the error parameter
}

Download tasks also has special delegates

1. Delegate to indicate that the download is complete. The file downloaded should be copied to a new location, as it will be deleted from the temporary location.

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                              didFinishDownloadingToURL:(NSURL *)location;

2. Delegate to indicate the download progress. The progress indicator can be updated based on the amount of data downloaded.

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                                           didWriteData:(int64_t)bytesWritten
                                      totalBytesWritten:(int64_t)totalBytesWritten
                              totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;

3. Delegate called when the download gets resumed

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                                      didResumeAtOffset:(int64_t)fileOffset
                                     expectedTotalBytes:(int64_t)expectedTotalBytes;

Upload task does not have special delegates but the delegate method below can be used to check the upload progress

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
                                didSendBodyData:(int64_t)bytesSent
                                 totalBytesSent:(int64_t)totalBytesSent
                       totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend;

Conclusion

There are a lot more delegates and Network APIs you can explore by yourself. Hope this article has given some understanding on Networking concepts.

iPhone Application Development

<< iPhone Application Development – Core DatabaseiPhone Application Development – Memory Management >>

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

No Reader comments

Comments on this post are closed.