Checking for valid IP for connection with NSURLConnection - iphone

I currently have an ap that attempts to open a webview based on certain servers I am communicating with.
However, I allow the user the capability to type in their own server IPs in case both the iphone/ipad and server(or other device) are not on the same network. However, I am attempting to use NSURLConnection to detect if I can open a connection with the given IP however NSURLConnection never returns an error, even if the server address(or even a random web address) is completely bogus.
the .h
#interface DetailViewController : UIViewController <UIPopoverControllerDelegate, UISplitViewControllerDelegate, UITableViewDataSource, UITableViewDelegate,UIWebViewDelegate, NSURLConnectionDataDelegate> {
the relevant code in the .m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath *)indexPath
{
dev_ip = #"http://www.asdfasfdfa.com/";
//dev_ip = (random ip)
NSMutableURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:dev_ip]];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (conn) {
NSLog(#"Connection established");
}
else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:[NSString stringWithFormat:#"No Device at designated IP"]
delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
}
}
this if/else always outputs 'Connection established.' Is this something NSURLConnection should not be used for? If so, what can I use to detect devices at given IP's for connectivity. I need to stop the user from attempting to connect to bad IP's so whats the best method in doing so?

NSURLConnection, when used with delegation, will call delegate methods when it connects, fails to connect and receive data. You should look into NSURLConnectionDelegate.
Here's a quick example:
// In your .h
#interface MyClass : NSObject <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
#end
EDIT You actually need both delegates.
// In your .m
#implementation MyClass
- (void)myMethodToConnect {
NSString *dev_ip = #"http://74.125.137.101"; // Google.com
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:dev_ip]];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
switch ([(NSHTTPURLResponse *)response statusCode]) { // Edited this!
case 200: {
NSLog(#"Received connection response!");
break;
}
default: {
NSLog(#"Something bad happened!");
break;
}
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(#"Error connecting. Error: %#", error);
}
#end
Also, just throwing it out there too, you don't necessarily have to use an asynchronous call. You can send a synchronous call which doesn't require you to implement a delegate. Here's how:
NSString *dev_ip = #"http://www.asdfasdfasdf.com/";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:dev_ip]];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *connectionData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
You can check the response value and errors.

There's a better way to test whether a server is valid or not. The Reachability class provides good API for this purpose.

Related

NSURLConnection doesn't receive data

I have implemented an NSURLConnection that sends a request to a server and receives some data back which is stored in an NSMutableData object. These are the methods that I implemented as part of NSURLConnectionDelegate:
-(void)upLoadBook:(NSMutableDictionary *)theOptions{
NSMutableString *theURL = [[NSMutableString alloc] initWithString:#"theURL"];
[theURL appendFormat:#"&Title=%#&Author=%#&Price=%#", [theOptions objectForKey:#"bookTitle"],
[theOptions objectForKey:#"bookAuthor"],
[theOptions objectForKey:#"bookPrice"]];
[theURL appendFormat:#"&Edition=%#&Condition=%#&Owner=%#", [theOptions objectForKey:#"bookEdition"],
[theOptions objectForKey:#"bookCondition"],
_appDel.userID];
NSLog(#"%#\n", theURL);
NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:theURL]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
// Create the NSMutableData to hold the received data.
// receivedData is an instance variable declared elsewhere.
receivedData = [NSMutableData data];
}
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse
*)response
{
// This method is called when the server has determined that it
// has enough information to create the NSURLResponse.
// It can be called multiple times, for example in the case of a
// redirect, so each time we reset the data.
// receivedData is an instance variable declared elsewhere.
[receivedData setLength:0];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// do something with the data
// receivedData is declared as a method instance elsewhere
//Receives a response after book has been uploaded (Preferably a Book ID...)
responseString = [[NSString alloc] initWithData:receivedData
encoding:NSUTF8StringEncoding];
NSLog(#"Response String: %#", responseString);
[_options setValue:responseString forKey:#"bookID"];
[self performSegueWithIdentifier:#"UploadSuccessSegue" sender:self];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Whoops." message:#" No internet
connection.\n Please make sure you have a connection to the internet."
delegate:self cancelButtonTitle:#"Ok"
otherButtonTitles: nil];
[alert show];
}
The function uploadBook seems to be called,however, I never get to didFinishLoading and didReceiveData never receives any data. What could be a possible problem. Any hints or clues would be much appreciated.
You need to add your NSURLConnection to the current run loop or a separate one (such as one you set up in a separate thread). The delegate methods do need to get CPU time, after all.
Looking at this related question's accepted answer, it can also be done via Grand Central Dispatch:
dispatch_async(dispatch_get_main_queue(), ^{
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
[conn start];
});
One thing for sure is that you should %-escape your list of parameter before trying to send the request.
You can use stringByAddingPercentEscapesUsingEncoding for that purpose:
NSMutableString *theURL = [[NSMutableString alloc] initWithString:#""];
[theURL appendFormat:#"&Title=%#&Author=%#&Price=%#", [theOptions objectForKey:#"bookTitle"],
[theOptions objectForKey:#"bookAuthor"],
[theOptions objectForKey:#"bookPrice"]];
[theURL appendFormat:#"&Edition=%#&Condition=%#&Owner=%#", [theOptions objectForKey:#"bookEdition"],
[theOptions objectForKey:#"bookCondition"],
_appDel.userID];
theURL = [NSStringWithFormat:#"YOUR_URL_HERE?",[theURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
Please, note that I refactored your code with the minimum number of changes to get the result. You can find better refactorizations for sure.
Here is a sample that works from one of my projects:
NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://www.brayden.me/analytics/device.php"]];
[urlRequest setHTTPMethod:#"POST"];
NSMutableString *postParams = [NSMutableString string];
[postParams appendFormat:#"session=%#&", analyticsSession];
[postParams appendFormat:#"device=%#&", device];
[postParams appendFormat:#"system=%#&", csystem];
[postParams appendFormat:#"version=%#&", version];
[postParams appendFormat:#"launch=%f&", totalLaunchTime];
if([Analytics_Location location].latitude && [Analytics_Location location].longitude) {
[postParams appendFormat:#"latitude=%#&", [Analytics_Location location].latitude];
[postParams appendFormat:#"longitude=%#&", [Analytics_Location location].longitude];
}
[urlRequest setHTTPBody:[postParams dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self startImmediately:YES];
[connection start];
Make sure your header method also uses . The code of mine should at least show you how to properly format the request, as I can verify this does receive data from a PHP call of mine.

NSUrlConnectionDelegate not calling methods to load data

I have looked at NSURLConnectionDelegate connection:didReceiveData not working already, but there didn't seem to be any good result from that, so I am curious why I am not able to get any data.
I put in breakpoints in didReceiveResponse and didReceiveData.
It does print out "connection succeeded", so I know that the connection is started.
I am using ARC for memory management.
- (void)load {
request = [NSMutableURLRequest requestWithURL:myURL
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:60];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (conn) {
[conn start];
NSLog(#"connection succeeded, %s", [myURL description]);
responseData = [NSMutableData data];
} else {
NSLog(#"connection failed");
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
responseData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
UPDATE:
To see how I test this look at Asynchronous unit test not being called by SenTestCase.
I did implement the two methods mentioned by jonkroll, in his answer, I just didn't show them, but, they also aren't being called.
I had added [conn start] only because it wasn't working, and I was hoping that may solve it, but no such luck.
When you declare your connection like this:
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
You are creating a local pointer. When your method completes, since it was the last strong reference to the NSURLConnection, ARC releases it. You need to use a strong ivar (and/or) property to hold a strong reference to the NSURLConnection you create.
Edit
Here is basic sample of code that I tested in a sample project. Give it a run. Verbose logging helps.
#implementation <#Your class here#> {
// With ARC ivars are strong by default
NSMutableData *_downloadedData;
NSURLConnection *_connection;
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
NSHTTPURLResponse *realResponse = (NSHTTPURLResponse *)response;
if (realResponse.statusCode == 200){
// Really any 2** but for example
_downloadedData = [[NSMutableData alloc] init];
NSLog(#"Good response");
} else {
NSLog(#"Bad response = %i",realResponse.statusCode);
}
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
if (connection == _connection){
[_downloadedData appendData:data];
NSLog(#"Getting data...");
}
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
if (connection == _connection){
_connection = nil;
NSLog(#"We're done, inform the UI or the delegates");
}
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
_connection = nil;
NSLog(#"Oh no! Error:%#",error.localizedDescription);
}
- (void)load {
NSURL *url = [NSURL URLWithString:#"http://www.google.com/"];
NSURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:60];
// Assign strong pointer to new connection
_connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
NSLog(#"Connection was initialized? = %#",(!!_connection)?#"YES":#"NO");
}
#end
The NSURLConnection method initWithRequest starts an asynchronous request for data from a url. Because the request is done asynchronously you can't expect to work with the response in the same method in which the request is invoked. Instead you need to do so in the NSURLConnection's delegate callback methods. You have already implemented didReceiveResponse: and didReceiveData:, but there are a couple others that will be useful to you.
If you want to look at the contents of the response you should do so in connectionDidFinishLoading:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// response is complete, do something with the data
NSLog(#"%#", responseData);
}
The fact that your code prints out "connection succeeded" doesn't really mean that the request was successful, only that the NSURLConnection object was created successfully. To test whether there was a problem with the connection you can implement the delegate method connection:didFailWithError:
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
Also there is no need to call [conn start]. The request will be started automatically when you call initWithRequest:
I suggest reading Apple's documentation on Using NSURLConnection for more details.

How to use more than one delegate in iphone?

I am using below code to use json but i need more url connection in same page, how to achive it, thanks in advance
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog([NSString stringWithFormat:#"Connection failed: %#", [error description]]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
//do something with the json that comes back ... (the fun part)
}
- (void)viewDidLoad
{
[self searchForStuff:#"iPhone"];
}
-(void)searchForStuff:(NSString *)text
{
responseData = [[NSMutableData data] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.whatever.com/json"]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
I am using php for web access
You could use instance variables to keep pointers to the connections. Then in the delegate callbacks, check for pointer equality to check which connection you're dealing with.
As NSValue conforms to NSCopying I use it to wrap the pointer to the connection, and use this as the key to access relevant data from a NSMutableDictionary. For example you might do something like the following:
-(void)searchForStuff:(NSString *)text withTarget:(id)target selector:(SEL)selector {
responseData = [[NSMutableData data] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.whatever.com/json"]];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:target,#"target",NSStringFromSelector(selector),#"selector",nil];
NSURLConnection *c = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[myMutableDictionary setObject:options forKey:[NSValue valueWithPointer:c]];
[c release];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSValue *p = [NSValue valueWithPointer:connection];
NSDictionary *options = [myMutableDictionary objectForKey:p];
if (options) {
id target = [options objectForKey:#"target"];
SEL selector = NSSelectorFromString([options objectForKey:#"selector"]);
if (target && selector && [target respondsToSelector:selector]) {
[target performSelector:selector withObject:responseData];
}
}
}
Don't do any of that.
Instead use the brilliant ASIHTTPRequest library, which makes everything much simpler and better. Literally, since I discovered ASI a couple years ago, I haven't written a single NSURLConnection, not one.
ASI's block interface lets you configure a request object with its handler code before firing it, and does away with any need for delegation.
__block ASIHTTPRequest *r = [ASIHTTPRequest requestWithUrl:myNSURLObject];
[r setCompletionBlock:^{
NSLog([r responseString]); //for instance
}];
[r startAsynchronous];
If blocks scare you, you can also point a particular request at a particular method, so different request types can be handled separately:
- (void) viewDidLoad { //or wherever
ASIHTTPRequest *r = [ASIHTTPRequest requestWithUrl:myFirstURL];
r.delegate = self;
[r setDidFinishSelector:#selector(requestDone:)];
[r startAsynchronous];
}
// then later on...
- (void)requestDone:(ASIHTTPRequest *)request
{
NSString *response = [request responseString];
}
You don't actually need more than one delegate. You need more than one NSURLConnection and you can test to see which one is calling the delegate method.
For example. Assuming the following instance variable (or properties):
NSURLConnection *connectionA;
NSURLConnection *connectionB;
NSMutableData *dataA;
NSMutalbeData *dataB;
First you instantiate each NSURLConnection variable
-(void)searchA:(NSString *)text
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://www.a.com/%#", text]]];
connectionA = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
-(void)searchB:(NSString *)text
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://www.b.com/%#", text]]];
connectionB = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
Then you can test to see which connection is calling the delegate method and customize the implementation based on the connection
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
if (connection == connectionA) {
[dataA appendData:data];
}
else if (connection == connectionB) {
[dataB appendData:data];
}
}
You'll need to do this for each delegate method.

Synchonous SSL certificate handling on iPhone

I was wondering if anyone can help me understand how to add SSL certificate handling to synchronous
connections to a https service.
I know how to do this with asynchronous connections but not synchronous.
NSString *URLpath = #"https://mydomain.com/";
NSURL *myURL = [[NSURL alloc] initWithString:URLpath];
NSMutableURLRequest *myURLRequest = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
[myURL release];
[myURLRequest setHTTPMethod:#"POST"];
NSString *httpBodystr = #"setting1=1";
[myURLRequest setHTTPBody:[httpBodystr dataUsingEncoding:NSUTF8StringEncoding]];
NSHTTPURLResponse* myURLResponse;
NSError* myError;
NSData* myDataResult = [NSURLConnection sendSynchronousRequest:myURLRequest returningResponse:&myURLResponse error:&myError];
//I guess I am meant to put some SSL handling code here
Thank you.
Using the static sendSynchronousRequest function is not posible, but i found an alternative.
First of all NSURLConnectionDataDelegate object like this one
FailCertificateDelegate.h
#interface FailCertificateDelegate : NSObject <NSURLConnectionDataDelegate>
#property(atomic,retain)NSCondition *downloaded;
#property(nonatomic,retain)NSData *dataDownloaded;
-(NSData *)getData;
#end
FailCertificateDelegate.m
#import "FailCertificateDelegate.h"
#implementation FailCertificateDelegate
#synthesize dataDownloaded,downloaded;
-(id)init{
self = [super init];
if (self){
dataDownloaded=nil;
downloaded=[[NSCondition alloc] init];
}
return self;
}
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace: (NSURLProtectionSpace *)protectionSpace {
NSLog(#"canAuthenticateAgainstProtectionSpace:");
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge {
NSLog(#"didReceiveAuthenticationChallenge:");
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[downloaded signal];
[downloaded unlock];
self.hasFinnishLoading = YES;
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[dataDownloaded appendData:data];
[downloaded lock];
}
-(NSData *)getData{
if (!self.hasFinnishLoading){
[downloaded lock];
[downloaded wait];
[downloaded unlock];
}
return dataDownloaded;
}
#end
And for use it
FailCertificateDelegate *fcd=[[FailCertificateDelegate alloc] init];
NSURLConnection *c=[[NSURLConnection alloc] initWithRequest:request delegate:fcd startImmediately:NO];
[c setDelegateQueue:[[NSOperationQueue alloc] init]];
[c start];
NSData *d=[fcd getData];
Now you will have all benefits of have an async use of nsurlconnection and benefits of a simple sync connection, the thread will be blocked until you download all data on the delegate, but you could improve it adding some error control on FailCertificateDelegate class
EDIT: fix for big data. based on Nikolay DS comment. Thanks a lot
I had a similar issue. In my case i had an a-synchronous connection working with ssl as required using the two delegate methods that allowed me to accept any certificate:
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
But i was stuck on doing the same in a synchronous manner. I searched the web until i found your post and unfortunately another stackoverflow post where it is hinted that you cannot perform synch calls on NSURLConnection and work with ssl (because of the lack of a delegate to handle the ssl authentication process).
What i ended up doing is getting ASIHTTPRequest and using that. It was painless to do and took me about an hour to set up and its working perfectly. here is how i use it.
+ (NSString *) getSynchronously:(NSDictionary *)parameters {
NSURL *url = [NSURL URLWithString:#"https://localhost:8443/MyApp/";
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
NSString *parameterJSONString = [parameters JSONRepresentation];
[request appendPostString:parameterJSONString];
[request addRequestHeader:#"User-Agent" value:#"MyAgent"];
request.timeOutSeconds = CONNECTION_TIME_OUT_INTERVAL;
[request setValidatesSecureCertificate:NO];
[request startSynchronous];
NSString *responseString = [request responseString];
if (request.error) {
NSLog(#"Server connection failed: %#", [request.error localizedDescription]);
} else {
NSLog(#"Server response: %#", responseString);
}
return responseString;
}
The important part of course is the
[request setValidatesSecureCertificate:NO];
Another alternative for you is to handle the download in another thread with an a-synch connection using the two methods above and block the thread from which you want the synch connection until the request is complete
Im close to finding the solution for this with the code below. This works but often crashes
probably because I am doing something wrong in the way I code this and I don't have a strong understanding of the methods used. But if anyone has any suggestions on how to improve this
than please post.
Just after the line:
NSError* myError;
and just before the line:
NSData* myDataResult = [NSURLConnection sendSynchronousRequest:myURLRequest
returningResponse:&myURLResponse error:&myError];
add:
int failureCount = 0;
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
initWithHost:#"mydomain.com" port:443 protocol:#"https" realm:nil
authenticationMethod:NSURLAuthenticationMethodServerTrust];
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:myURL MIMEType:#"text/html"
expectedContentLength:-1 textEncodingName:nil];
NSURLAuthenticationChallenge *challange = [[NSURLAuthenticationChallenge alloc]
initWithProtectionSpace:protectionSpace proposedCredential:[NSURLCredential
credentialForTrust:protectionSpace.serverTrust] previousFailureCount:failureCount
failureResponse:response error:myError sender:nil];

Asynchronous vs synchronous methods on iphone

I saw there is a method for synchronous, like if I wanted to do something like:
-(IBAction)doNSURLConnSync {
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSError *error = nil;
NSURLResponse *response = nil;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
}
How does it perform differently than if I did asynchronous:
-(IBAction)doNSURLConnASync {
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self];
if (connection) {
responseData = [[NSMutableData alloc] init];
[webview loadHTMLString:#"" baseURL:nil];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}
else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Network error occured"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#"%s", __FUNCTION__);
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[connection release]; // got passed in as a param. we are done with it now.
[webview loadData:responseData
MIMEType:nil
textEncodingName:nil
baseURL:nil];
[responseData release];
}
Also, with my doNSURLConnSync method, I am just trying to load a UIWebView. Is there a reason why it doesn't? The button just sits there and stays highlighted, while it tries to access the webpage, but does nothing in the end, compared to the asynchronous version.
Also, for networkactivityindicator in my asynchronous code, I wanted to set my UIWebView to blank, have the indicator on while my webview loads, and then turn off the network activity indicator once the page loads. However, if I delete the loadHTMLString method, the network activity indicator works as it's supposed to, but with the loadHTMLString, the UIWebView goes blank, but the network activity indicator does not. Any thoughts? Thanks.
First, for the syncrhonous:
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error
This is the method signature, when you call the synchronous request, it wil return the data for you to display on the UIWebView and you have to call the UIWebView to display the data. However, the synchronous calling will block your UI until all the data come back. So, be careful with UX.
NSUrlConnection sendSynchronousRequest
For the asynchronous, it will not block your UI, user can still do everything they want with it, like go back to the previous screen. So, usually, it is recommended for big and long network
I don't know why it doesn't show your indicator. But why do you need this line : [webview loadHTMLString:#"" baseURL:nil]; . You only need to call it after you got your HTML response
A synchronous request ties up the main thread, which you should reserve for UI widget updates.
Doing an asynchronous request on a background thread frees up the main thread to update the UI.
Pull your UI update code (indicator view and web view) into separate methods, calling them on the main thread with -performSelectorOnMainThread:withObject:waitUntilDone:
[self performSelectorOnMainThread:#selector(updateWebview) withObject:nil waitUntilDone:YES];