Most of the iPhone applications require the images to be downloaded from the web server. Depending upon the web service (API) provided, there are some methods to download the image. In this tutorial we will explain how to download the image from a remote server using NSURLConnection Delegates. Later we will explain how to save the image in application bundle (i.e Documents folder) for future use.
Open Xcode, select “Create a new Xcode project,” and click Next. Choose the Single View Application template as shown in the following figure.
Click Next, then you navigate to the next screen. Fill all the fields like product name (ImageDownload), organization name and etc. In the bottom of the screen just uncheck “Use Storyboards”(As I have use the nib files in this application) and “Include Unit Tests” as shown in the following figure.
Then click Next button.
Open the ViewController.xib file and add the required outlets as shown below.
Here UIProgressView outlet shows how much percentage of data has been downloaded. After downloading the full data, UIImageView will display the downloaded image.
Finally, connect these outlets with the reference objects in ViewController.h file. Following figure shows the required connections.
Now open the ViewController.h file and add the following code.
@interface ViewController : UIViewController<NSURLConnectionDelegate,NSURLConnectionDataDelegate>
@property(nonatomic, strong) NSMutableData *imageData;
@property(nonatomic, assign) float length;
@property(nonatomic, strong) IBOutlet UIProgressView *progressView;
@property(nonatomic, strong) IBOutlet UIImageView *imageView;
@property(nonatomic, strong) IBOutlet UILabel *timeLabel;
– (void)saveLocally:(NSData *)imgData;
@end
Here “imageData” will contains the data downloaded from server, “length” will contains the total image data length. And NSURLConnectionDelegate, NSURLConnectionDataDelegate are the delegate protocols for tracking the image data response, how much data is downloaded, and failure responses.
Now open the ViewController.m file. In viewDidLoad method, add the following lines of code.
[NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.raincoast.org/wp-content/uploads/S1I1596grizzlysittingattideline547-10MB.jpg"]]delegate:self];
Here we will download the image from URL http://www.raincoast.org/wp-content/uploads/S1I1596grizzlysittingattideline547-10MB.jpg For the best progress of the progress view, we have taken the image of size 10MB.
Now for responding to authentication challenges we need to implement the delegate protocols. From the following code, in “didReceiveResponse” delegate we will find the expected length of the total image data for calculating the percentage of image downloaded. This delegate will call only once for each connection. The delegate “didReceiveData” will call several times until the entire image data is downloaded. In this delegate, we append the downloaded data to “imageData” and also added the code for calculating percentage of image downloaded. “connectionDidFinishLoading” delegate will call when entire image data is downloaded. Here we handle the image display part. Implementation of delegate methods is as follows:
{
self.length = [response expectedContentLength];
}
– (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.imageData appendData:data];
float progress = (float)[imageData length]/(float)self.length;
self.timeLabel.text = [NSString stringWithFormat:@"%0.2f%%",progress*100];
[self.progressView setProgress:progress animated:YES];
}
– (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"didFailWithError");
}
– (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
UIImage *img = [UIImage imageWithData:self.imageData];
self.imageView.image = img;
[self saveLocally:self.imageData];
}
Now compile and run the code. You will see the accurate download progress view and downloaded image as follows:
Some applications need the local storage of data to avoid the same data to be downloaded several times. To achieve the local storage we need to save this image locally into applications document folder. “saveLocally:” method will do the local storage.
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSDate *aDate = [NSDate date];
NSTimeInterval interval = [aDate timeIntervalSince1970];
NSString *localFilePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%d.jpeg",(int)interval]];
[imgData writeToFile:localFilePath atomically:YES];
}
Here for each image download, we are giving a deferent name as per the epoch time. Now compile and run the code, you will see the image to be saved in applications document folder. Documents folder for your application is located in the following path /Users/startup/Library/Application Support/iPhone Simulator/6.1/Applications/3747D38D-9D04-4A58-9327-DFEE22740A81/Documents. Following screenshot shows the saved image under documents folder of the application.