Plasma
Plasma

Reputation: 2912

Getting data from NSURLConnection using blocking or similar

Hi guys this will be my first post and am pretty new to Objective-C though not entirely new to coding. I've been doing a lot of reading and a lot of Googling and a lot of my answers have come from this site. So now I'm really stuck I figured it was about time I asked the experts.

I'm basically trying to get the raw HTML data from a given URL so that I can parse it for information. I have all the parsing sorted, and can retrieve the raw HTML however I'm struggling to understand how to get the program to stop while the data arrives from NSURLConnection so I can use it. Currently my program whizzes past the connection and the holding String gets left as empty, until shortly after when its filled by the request. I believe I need to use a "Syncronous" connection but this is frowned upon because it freezes the UI while its processing the request. I'm trying to call it like this ....

urlData = [getURLClass getURL: @"http://www.google.co.uk"];

Hoping to get raw HTML in to the String urlData so I can parse it.My current code from my class is below....

//Create the request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];

//Open NSURLConnection with 'request'
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    //If we receive something
    if (data) {
        //Pass and decode to string
        receivedData = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
        NSLog(@"Received HTML: %@", receivedData); 
    }

    //Something went wrong
    else {
       // ToDO: Sort out any errors

    }
}];

return receivedData;

When this is run the log shows "Received HTML: nil" and the return value is also blank, but if I wait a moment then call the class again its been filled with data from the previous request. I did try another method which the data was retrieved in to

-(void) connectionDidFinishLoading

But this leaves me the problem that I cannot "return" the data from the Method that was called. As I said I'm very new to Objective-C. I'm aware there are discontinued wrappers like ASIHTTPRequest, but I'm sure there is a simpler answer to this than using someone else's class. It will also help me to learn if I can find an answer, I simply need to get the program to wait while the data is received before the class return it. I may be trying to run before I can walk with Obj-C, but my program is useless unless I can interact with the web.

Thanks in advance. Plasma

Upvotes: 0

Views: 4960

Answers (3)

TheEye
TheEye

Reputation: 9346

You should be able to do what you want with the NSString function initWithContentsOfURL:

NSError* error;
NSString* htmlData = [[NSString alloc] initWithContentsOfURL:myURL encoding:NSUTF8StringEncoding error:&error];

It might also be NSASCIIStringEncoding for the encoding ... but in any case it gives you the string synchronously.

EDIT:

Corrected Spelling initWithContent*s*OfURL, added alloc

Upvotes: 2

Glenn Smith
Glenn Smith

Reputation: 912

I wrote a class file for this type of situation.

CAURLDownload.h:
http://localhostr.com/file/vGtIIpO/CAURLDownload.h

CAURLDownload.m:
http://localhostr.com/file/TAieiAE/CAURLDownload.m

Basically, you want to call
[CAURLDownload downloadURL:URL target:self selector:@selector(finishedSelector: connection:) failSelector:@selector(failureSelector:) userInfo:userInfo];

URL is an NSURL and userInfo is an NSDictionary.

Basically, you call that method with the appropriate parameters and execute your parsing in finishedSelector. Example:

[CAURLDownload downloadURL:[NSURL URLWithString:@"http://couleeapps.hostei.com"]
                    target:self
                  selector:@selector(downloadFinished:connection:)
              failSelector:@selector(downloadFailed:)
                  userInfo:nil];

And for the methods:

- (void)downloadFinished:(NSData *)recievedData conneciton:(CAURLDownload *)connection {
    //Parse recievedData
    NSString *recievedString = [[[NSString alloc] initWithData:recievedData] autorelease];
    //Etc.
}

- (void)downloadFailed:(CAURLDownload *)connection {
    NSLog(@"Download Failed!");
    //Do something
}

This has both the upsides of not locking the UI, being memory-friendly, and callable without a pointer required (singleton).

Upvotes: 1

jsd
jsd

Reputation: 7693

Unfortunately the SDK as supplied by Apple doesn't have any convenience functions to make this super simple. You have to do it all yourself using NSURLConnection. What I do is make a wrapper class that executes the NSURLConnection and then when the data is completely received it calls a completion block that you provide.

Upvotes: 0

Related Questions