iOS - Async NSURLConnection inside NSOperation - ios

I know this question was asked many times on SO, but I didn't manage to make it work in my project...
So, I want to subclass NSOperation and make it download a file using NSURLConnection. What is the right way to do it?
here is my code which doesn't work:
First, I'm adding all my operations in a loop:
DownloadFileOperation *operation;
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
for (int i=0; i<10; i++) {
operation = [[DownloadFileOperation alloc] init];
operation.urlString = pdfUrlString;
[queue addOperation:operation];
operation = nil; }
And here is my subclass:
#interface DownloadHandbookOperation : NSOperation <NSURLConnectionDelegate>
{
}
#property (strong, nonatomic) NSString *urlString;
#end
#implementation DownloadHandbookOperation
{
NSString *filePath;
NSFileHandle *file;
NSURLConnection * connection;
}
- (void)start
{
if (![NSThread isMainThread])
{
[self performSelectorOnMainThread:#selector(start) withObject:nil waitUntilDone:NO];
return;
}
NSURL *url = [[NSURL alloc] initWithString:[self.urlString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
[req addValue:#"Basic ***=" forHTTPHeaderField:#"Authorization"];
connection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];
}
- (void)connection:(NSURLConnection *)conn didReceiveResponse:(NSURLResponse *)response
{
NSString *filename = [[conn.originalRequest.URL absoluteString] lastPathComponent];
filename = [filename stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:filename];
[[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
file = [NSFileHandle fileHandleForUpdatingAtPath:filePath] ;
if (file)
{
[file seekToEndOfFile];
}
else
[self finish];
}
- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data
{
if (file) {
[file seekToEndOfFile];
}
[file writeData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)conn
{
[file closeFile];
[self finish];
}
- (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error
{
connection = nil;
[self finish];
}
- (void)cancel
{
[super cancel];
[connection cancel];
}
- (void)finish
{
NSLog(#"operationfinished.");
}
#end
What am I doing wrong?

You need to properly configure your operation to execute as a "concurrent operation"
Concurrency Programming Guide: Configuring Operations for Concurrent Execution
You need to return isConcurrent = YES and properly manage the other state flags, isExecuting and isFinished in a KVO compliant manner.
To illustrate the general idea here is a post from the engineers at Pulse that describes their solution with some easy to follow demo code you can download and review.
Pulse Engineering Blog: Concurrent Downloads using NSOperationQueues **
This code also handles the requirement that NSURLConnection is started on a thread with an active runloop by ensuring that it starts it on the main thread.
(** link is now to archive.org, I think pulse was acquired and have taken their old site down)

Related

Pause a download in objective-c

I'm unsure of what the best approach is for pausing a download. I have seen this question asked on stack over flow before, but doesn't seem to achieve the results I am looking for. For example: I understand inside of the AppDelegate, the - (void)applicationWillResignActive:(UIApplication *)application is called if a phone call comes on the phone for example. It is crucial for my app to successfully download the database to function appropriately. Here's the code I use to download the database:
NSString *urlDb = [NSString stringWithFormat:#"someURl'];
//---Create URL from where DB has to be download-----
NSURL *url = [NSURL URLWithString:urlDb];
NSError *error = nil;
NSData *data = [NSData dataWithContentsOfURL:url options:0 error:&error];
Pausing a download may not be critical for example, AT&T, but folks with Verizon cannot talk and download at the same time. Any help would be greatly appreciated. Thanks!
If you want pause/resume functionality, then you must use either old NSURLConnection, and implement all required delegate methods, or you can use new NSURLSession API.
Here is a basic implementation with NSURLConnection:
#property NSFileHandle *fileHandle;
#property NSURLConnection *connection;
// start download
- (IBAction)downloadButtonPressed
{
NSURL *url = [NSURL URLWithString:#"myUrl"];
NSURLRequest *dataRequest = [NSURLRequest requestWithURL:url];
self.connection = [NSURLConnection connectionWithRequest:dataRequest delegate:self];
[connection start];
}
Implement delegate methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
self.fileHandle = [NSFileHandle fileHandleForWritingAtPath:#“pathToYourFile”];
[self.fileHandle seekToEndOfFile];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.fileHandle writeData:data];
}
If you want to pause - just cancel connection like this:
[self.connection cancel];
Then you can resume like this:
- (void)resumeDownload
{
NSURL *url = [NSURL URLWithString:#"myUrl"];
NSMutableURLRequest *dataRequest = [NSMutableURLRequest requestWithURL:url];
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:pathToYourFile error:&attributesError];
NSNumber *fileSizeNumber = [fileAttributes objectForKey:NSFileSize];
NSString *bytesRangeHeader = [NSString stringWithFormat:#"bytes=%lld-", [fileSizeNumber longLongValue];
[_request setValue:bytesRangeHeader forHTTPHeaderField:#"Range"];
self.connection = [NSURLConnection connectionWithRequest:dataRequest delegate:self];
[connection start];
}

NSURLConnection delegate methods

I am using a button action to update the value of a MySQL table field. The update is perform in the web server, but I need to update a UILabel text in my view Controller.
This is the code I have implemented:
- (IBAction)votarAction:(id)sender {
//URL definition where php file is hosted
dispatch_queue_t backgroundQueue = dispatch_queue_create("com.mycompany.myqueue", 0);
dispatch_async(backgroundQueue, ^{
int categoriaID = [[detalleDescription objectForKey:#"idEmpresa"] intValue];
NSString *string = [NSString stringWithFormat:#"%d", categoriaID];
NSLog(#"ID EMPRESA %#",string);
NSMutableString *ms = [[NSMutableString alloc] initWithString:#"http://mujercanariasigloxxi.appgestion.eu/app_php_files/cambiarvaloracionempresa.php?id="];
[ms appendString:string];
// URL request
NSLog(#"URL = %#",ms);
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:ms]];
//URL connection to the internet
NSURLConnection *connection=[[NSURLConnection alloc]initWithRequest:request delegate:self];
dispatch_async(dispatch_get_main_queue(), ^{
//update your label
});
});
}
#pragma NSURLConnection Delegate Methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
//buffer is the object Of NSMutableData and it is global,so declare it in .h file
buffer = [NSMutableData data];
NSLog(#"ESTOY EN didReceiveResponse*********");
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(#"ESTOY EN didReceiveDATA*********");
[buffer appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//Here You will get the whole data
NSLog(#"ESTOY EN didFINISHLOADING*********");
NSError *jsonParsingError = nil;
NSArray *array = [NSJSONSerialization JSONObjectWithData:buffer options:0 error:&jsonParsingError];
//And you can used this array
NSLog(#"ARRAY = %#",array);
//HERE LABEL.TEXT UPDATE CODE
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"ERROR de PARSING");
NSLog(#"ESTOY EN didFAILWITHERROR*********");
}
As I told you, the field value at the MySQL table is updated every time the button is tapped, but the problem is that the NSURLConnection delegate methods are never called.
Any help is welcome
In your view controller's header file add: <NSURLConnectionDelegate>
Also, there's no need to throw the NSURLConnection into a seperate background process, maybe that's why the delegates aren't called. NSURLConnection is already asynchronous
Perhaps try something like this:
- (IBAction)votarAction:(id)sender
{
int categoriaID = [[detalleDescription objectForKey:#"idEmpresa"] intValue];
NSString *originalString = [NSString stringWithFormat:#"%d", categoriaID];
NSMutableString *mutablesString = [[NSMutableString alloc] initWithString:#"http://mujercanariasigloxxi.appgestion.eu/app_php_files/cambiarvaloracionempresa.php?id="];
[mutableString appendString:originalString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:mutableString]];
request.cachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;
request.timeoutInterval = 5.0;
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:
^(NSURLResponse *response, NSData *data, NSError *connectionError)
{
if (data)
{
NSArray *array = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
dispatch_async(dispatch_get_main_queue(), ^
{
// Update your label
self.label.text = [array objectAtIndex:someIndex];
});
}
else
{
// Tell user there's no internet or data failed
}
}];
}

NSURLConnection delegate methods are not being called

I am trying to download a set of files from a web server using NSURLConnection but at the point the connection appears to be made, the connection's delegate methods never get fired and so the file never gets downloaded. I have read many answers on SO and other sources and have tried the fixes that have been advised but to no avail, which makes me think I have made a different mistake here.
I have a viewController (InitViewController.m) which loads another class's method:
GetData *getDataInstance = [[GetData alloc] init];
[getDataInstance startUpdate];
GetData.m then does some checking and runs the class in charge of getting the files:
GetFiles *getFilesInstance = [[GetFiles alloc] init];
[getFilesInstance doFilesNeedDownloading];
doFilesNeedDowngoading method checks to see if we need the file and then runs getFiles:
-(void)getFile//:(NSString *) fullURL
{
// I have checked if the connection is run on the main thread and it is
NSLog(#"Is%# main thread", ([NSThread isMainThread] ? #"" : #" NOT"));
NSURL *downloadURL = [NSURL URLWithString:fullURL];
NSMutableURLRequest *dlRequest = [NSMutableURLRequest requestWithURL:downloadURL];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:dlRequest delegate:self];
[theConnection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[theConnection start];
if(theConnection) { //me checking for connection which is 'true'
NSLog(#"Connection for %# worked", fullURL);
} else {
NSLog(#"Connection for %# failed", fullURL);
}
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
responseData = [[NSMutableData alloc] init];
NSString *fileName = [[NSURL URLWithString:fullURL] lastPathComponent];
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) objectAtIndex:0]stringByAppendingPathComponent:fileName];
[[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
file = [NSFileHandle fileHandleForUpdatingAtPath:filePath];
[file seekToEndOfFile];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
[file seekToEndOfFile];
[file writeData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
[file closeFile];
}
I did originally fire the getDataInstance startUpdate in a separate thread in an update to have the 'getting data' part of the app separate to the 'UI building' part of the app and thought this might be the issue but for now I have remove that and even put in'[theConnection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]' as per other answers to this kind of question on SO.
I'm sure there will be something really obvious that I have missed, any ideas?
Thanks,
EDIT
I have now tried this code again but in the initViewController so this is pretty much the first thing that is fired when the app loads. This is no longer in another class or thread etc.:
-(void)getFile
{
fullURL = #"http://myURL.com/terms-and-conditions.txt";
NSURL *downloadURL = [NSURL URLWithString:fullURL];
NSMutableURLRequest *dlRequest = [NSMutableURLRequest requestWithURL:downloadURL];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:dlRequest delegate:self];
[theConnection start];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
responseData = [[NSMutableData alloc] init];
NSString *fileName = [[NSURL URLWithString:fullURL] lastPathComponent];
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) objectAtIndex:0]stringByAppendingPathComponent:fileName];
[[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
file = [NSFileHandle fileHandleForUpdatingAtPath:filePath];
[file seekToEndOfFile];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
[file seekToEndOfFile];
[file writeData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
[file closeFile];
}
getFile gets fired but it's delegate methods still don't get fired?
If you create NSURLConnection in other thread you have to manually start the run loop.
Try with this:
-(void)getFile
{
NSURL *downloadURL = [NSURL URLWithString:fullURL];
NSMutableURLRequest *dlRequest = [NSMutableURLRequest requestWithURL:downloadURL];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:dlRequest delegate:self];
[theConnection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
[theConnection start];
if(theConnection) { //me checking for connection which is 'true'
NSLog(#"Connection for %# worked", fullURL);
} else {
NSLog(#"Connection for %# failed", fullURL);
}
}
I had this problems too when I wanted to start NSURLConnection in a concurrent NSOperation.
Performing connection on main thread helped me solve the problem.
- (void)start {
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:#selector(start)
withObject:nil
waitUntilDone:NO];
return;
}
}
Also scheduling sonnection in [NSRunLoop currentRunLoop] helped me to solve the problem:
self.connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self
startImmediately:NO];
[self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSRunLoopCommonModes];
[self.connection start];
You can take a look how it's done in CSMessage class that is part of CSUtils framework. Feel free to use given code on your own: https://github.com/cloverstudio/CSUtils
Put delegate in your class.h like:
#interface InitViewController : UIViewController<NSURLConnectionDelegate,NSURLConnectionDataDelegate>
In the end I re-wrote the whole class and got the delegates firing.
NSString *currentURL = [NSString stringWithFormat:#"%#/api/sync", apiURL];
NSLog(#"URL = %#", currentURL);
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:currentURL]];
[request addValue:#"application/json" forHTTPHeaderField:(#"Accept")];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
Here are the delegates that now fire:
- (void)connection:(FileURLConnection*)connection didReceiveResponse:(NSURLResponse *)response
{
NSString *fileName = [[response URL] lastPathComponent];
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]stringByAppendingPathComponent:fileName];
[[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
connection.file = [NSFileHandle fileHandleForUpdatingAtPath:filePath];
}
- (void)connection:(FileURLConnection *)connection didReceiveData:(NSData *)data
{
[connection.file writeData:data];
}
- (NSCachedURLResponse *)connection:(FileURLConnection *)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse
{
return nil;
}
- (void)connectionDidFinishLoading:(FileURLConnection *)connection
{
[connection.file closeFile];
}
- (void)connection:(FileURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"GetFiles - didFailWithError - error : %# for URL %#", error, connection.currentRequest.URL);
}
The class now downloads the file (from my own API) and saves it on the device.
Just change this line and rest keep as it is in your code. Keep the scheduleInRunLoop line also.
NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self startImmediately:NO];

Objective C: Downloading File With Progress Bar [duplicate]

This question already has an answer here:
how to display progressbar during downloading video file from the server in to the iphone?
(1 answer)
Closed 9 years ago.
I am trying to put a progress bar that syncs during the download that is happening.
My app now can download a file using with this codes...
pdfData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:#"http://webaddress.com/pro/download/file.pdf"]];
NSString *resourcePDFPath = [[NSString alloc] initWithString:[[[[NSBundle mainBundle] resourcePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:#"Documents"]];
pdfFilePath = [resourcePDFPath stringByAppendingPathComponent:#"myPDF.pdf"];
[pdfData writeToFile:pdfFilePath atomically:YES];
During the process of this code the app stopped during download, is it normal?
Now what I want is to put a progress bar during that stop time while downloading.
I tried looking into the codes I found online but I'm a bit confused, I think I need a step-by-step-well-explained reference.
Using AFNetworking,
here progress is the UIProgressview
#import <AFNetworking/AFNetworking.h>//add to the header of class
-(void)downloadShowingProgress
{
progress.progress = 0.0;
currentURL=#"http://www.selab.isti.cnr.it/ws-mate/example.pdf";
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:currentURL]];
AFURLConnectionOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"MY_FILENAME_WITH_EXTENTION.pdf"];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:filePath append:NO];
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, NSUInteger totalBytesRead, NSUInteger totalBytesExpectedToRead) {
progress.progress = (float)totalBytesRead / totalBytesExpectedToRead;
}];
[operation setCompletionBlock:^{
NSLog(#"downloadComplete!");
}];
[operation start];
}
Using NSURLConnection
-(void)downloadWithNsurlconnection
{
NSURL *url = [NSURL URLWithString:currentURL];
NSURLRequest *theRequest = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
receivedData = [[NSMutableData alloc] initWithLength:0];
NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self startImmediately:YES];
}
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
progress.hidden = NO;
[receivedData setLength:0];
expectedBytes = [response expectedContentLength];
}
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[receivedData appendData:data];
float progressive = (float)[receivedData length] / (float)expectedBytes;
[progress setProgress:progressive];
}
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
- (NSCachedURLResponse *) connection:(NSURLConnection *)connection willCacheResponse: (NSCachedURLResponse *)cachedResponse {
return nil;
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *pdfPath = [documentsDirectory stringByAppendingPathComponent:[currentURL stringByAppendingString:#".mp3"]];
NSLog(#"Succeeded! Received %d bytes of data",[receivedData length]);
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[receivedData writeToFile:pdfPath atomically:YES];
progress.hidden = YES;
}
Use ASIHTTPRequest.h class and ASINetworkQueue.h for downloading the file.
and use this code for progress bar
request = [ASIHTTPRequest requestWithURL:#"http://webaddress.com/pro/download/file.pdf];
[request setDelegate:self];
[request setDownloadProgressDelegate:progressView];
[request setShowAccurateProgress:YES];
request.shouldContinueWhenAppEntersBackground=YES;
request.allowResumeForFileDownloads=YES;
[request startAsynchronous];
this may help you
I'm afraid it's not normal, use asynchronous method to get the NSData.
First of all you should be clear whether to make a synchronous call or asynchronous.
For mobile apps or any other app asynchronous is preferred one.
Once you are clear use NSURLConnection class to fetch the data from the URL.
Here is the good tutorial.
And for loading you can start progress while starting the request and stop it when you receive connection:didFailWithError: or connectionDidFinishLoading: delegate method.

Object-c/iOS :How to use ASynchronous to get a data from URL?

My friend saw my code, a part is get a plist data from URL
And he told me not to use Synchronous,Use ASynchronous
But I don't know how to do ASynchronous in simple way
This is the code I use in my program
NSURL *theURL = [[NSURL alloc]initWithString:#"http://someurllink.php" ];
NSURLRequest *theRequest=[NSURLRequest requestWithURL:theURL
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSData *returnData = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:nil error:nil];
NSString *listFile = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
self.plist = [listFile propertyList];
[self.tableView reloadData];
[listFile autorelease];
How can I change my code use ASynchronous to get the data ?
Great thanks for all reply and answers : )
Short answer: You can use
+ (NSURLConnection *)connectionWithRequest:(NSURLRequest *)request delegate:(id)delegate;
See NSURLConnectionDelegate for the informal delegate protocol (all methods are optional)
Long answer:
Downloading data asynchronously is not as straightforward as the synchronous method. First you have to create your own data container e.g. a file container
//under documents folder/temp.xml
file = [[SomeUtils getDocumentsDirectory] stringByAppendingPathComponent:#"temp.xml"]
NSFileManager *fileManager = [NSFileManager defaultManager];
if(![fileManager fileExistsAtPath:file]) {
[fileManager createFileAtPath:file contents:nil attributes:nil];
}
When you connect to server:
[NSURLConnection connectionWithRequest:myRequest delegate:self];
You have to fill the container with the data you receive asynchronously:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSFileHandle *fileHandle = [NSFileHandle fileHandleForUpdatingAtPath:file];
[fileHandle seekToEndOfFile];
[fileHandle writeData:data];
[fileHandle closeFile];
}
You have to manage errors encountered using:
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
If you want to capture the server response:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response
Handle when connection finished loading:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
For asynchronous fetch of HTML source code, I recommend you to use AFNetworking
1) Then subclass AFHTTPCLient, for example:
//WebClientHelper.h
#import "AFHTTPClient.h"
#interface WebClientHelper : AFHTTPClient{
}
+(WebClientHelper *)sharedClient;
#end
//WebClientHelper.m
#import "WebClientHelper.h"
#import "AFHTTPRequestOperation.h"
NSString *const gWebBaseURL = #"http://dummyBaseURL.com/";
#implementation WebClientHelper
+(WebClientHelper *)sharedClient
{
static WebClientHelper * _sharedClient = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:gWebBaseURL]];
});
return _sharedClient;
}
- (id)initWithBaseURL:(NSURL *)url
{
self = [super initWithBaseURL:url];
if (!self) {
return nil;
}
[self registerHTTPOperationClass:[AFHTTPRequestOperation class]];
return self;
}
#end
2) Request asynchronously HTML source code, put this code in any relevant part
NSString *testNewsURL = #"http://whatever.com";
NSURL *url = [NSURL URLWithString:testNewsURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *operationHttp =
[[WebClientHelper sharedClient] HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSString *szResponse = [[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding] autorelease];
NSLog(#"Response: %#", szResponse );
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Operation Error: %#", error.localizedDescription);
}];
[[WebClientHelper sharedClient] enqueueHTTPRequestOperation:operationHttp];

Resources