NSURLConnection not responding
Asked Answered
D

5

3

I'm trying to get some data from an URL, but for some reason, nothing happens when I do the following. Neither didReceiveResponse:, didReceiveData:, didFailWithError: or connectionDidFinishLoading: are reached, except when I add a timeout to my request by doing this: [request setTimeoutInterval:10.0]

Here's what I'm doing :

-(void)getConfigFromServer{
    [self getContentAtURL:kUrlGetUser];
}

//Va chercher le contenu à l'URL passée en paramètre
- (void)getContentAtURL: (NSURL *)url {

    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    NSString * userLogin = [userDefaults objectForKey:@"UserLogin"];
    NSString * userPassword = [userDefaults objectForKey:@"UserPassword"];
    NSURL * urlFinal = [NSURL URLWithString:[NSString stringWithFormat:@"%@", url]];
    NSLog(@"Request : %@", [NSString stringWithFormat:@"%@", url]);
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:urlFinal];  
    [request setHTTPShouldHandleCookies:NO];
    [request setTimeoutInterval:10.0];

    NSString *sourceString = [NSString stringWithFormat:@"%@:%@", userLogin, userPassword]; 
    NSData * sourceData = [sourceString dataUsingEncoding:NSUTF8StringEncoding];  
    NSString *authString = [sourceData base64EncodedString];  

    authString = [NSString stringWithFormat: @"Basic %@", authString];
    [request setValue:authString forHTTPHeaderField:@"Authorization"];
    [request setValue:@"text/xml" forHTTPHeaderField:@"Accept"];
    NSURLConnection * connection=[NSURLConnection connectionWithRequest:request delegate:self];

    if(connection){
        NSLog(@"Connection started");
        receivedData = [NSMutableData data];
    }else{
        NSLog(@"Error while trying to initiate the connection");
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    [receivedData setLength:0];
    if ([response respondsToSelector:@selector(statusCode)])
    {
        int statusCode = [((NSHTTPURLResponse *)response) statusCode];
        if (statusCode >= 400)
        {
            [connection cancel];  // stop connecting; no more delegate messages
            NSDictionary *errorInfo
                = [NSDictionary dictionaryWithObject:[NSString stringWithFormat:
                NSLocalizedString(@"Server returned status code %d",@""),
                statusCode]
                    forKey:NSLocalizedDescriptionKey];
            NSError *statusError = [NSError errorWithDomain:@"Error"
                code:statusCode
                userInfo:errorInfo];
            [self connection:connection didFailWithError:statusError];
        }
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    [receivedData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    NSLog(@"Connection failed! Error - %@ %@",[error localizedDescription],[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    [self fetchedData:receivedData];
}

EDIT : I'm still having this problem, and now have it on the actual device too. As I said it in the comments, I use ARC on this app for the first time, and I'm using XCode 4.2.

Any idea?

Dansby answered 20/2, 2012 at 15:6 Comment(7)
are you sure the server is online?Nellanellda
Please tell, what is called when you set timeout? Request gets loaded or fails? If the latter, tell us error text. Default timeout is 60s, make sure you're patient enough to wait until failure methods are called.Pinfeather
Yes, the server is online. Tried with many URL, to make sure it wasn't the problem. When setting the timeout, I'm getting this : Connection failed! Error - The request timed out. followed by the URL.Dansby
Do you get any warnings at compile-time? What i mean is: i see you'd set this 'self' as a connection delegate, but did you declare it as an implementor of NSURLConnectionDelegate protocol in it's .h file?Kush
Nope, no warning. And yes, I'm implementing the NSURLConnectionDelegate protocol.Dansby
You should modify your question (you mentioned below that "sometimes it just works") - it's an important piece of informationKush
I have the same issue. It is random, often it works fine, othertimes the delegate methods never get called, and the default timeout (3 or 4 minutes) triggers. The interesting thing is, once this starts to happen all requests to the same server will timeout. If the first request works, then they all work.Unsuspecting
A
8

This is old thread but still this answer might help someone out there.

If you are calling this in background thread, check whether you thread is exiting before delegates is called.

Try doing this.

NSURLConnection * connection = [[NSURLConnection alloc] 
                                initWithRequest:request
                                       delegate:self startImmediately:NO];

[connection scheduleInRunLoop:[NSRunLoop mainRunLoop] 
                      forMode:NSDefaultRunLoopMode];
[connection start];
Ancestral answered 26/8, 2013 at 5:56 Comment(2)
THANK YOU @SRIKANTH! I had an NSURLConnection that was properly firing off the request but never seeing ANY response. All I had to do was add startImmediately:NO and [scheduleInRunLoop: forMode:] to fix it.Eric
I'd give you +100 if I could!Pteranodon
R
0

You're passing an NSURL to your getContentAtURL but then treating it as though it was a string in :

NSURL * urlFinal = [NSURL URLWithString:[NSString stringWithFormat:@"%@", url]];

try changing it to:

NSURL * urlFinal = [NSURL URLWithString:[NSString stringWithFormat:@"%@", [url absoluteString]]];

btw, you know you're not using your login and password don't you?

EDIT:

When you say receivedData = [NSMutableData data]; what is data?

I think that might be the problem.

I tend to use the following to setup the data object when data first arrives:

- (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)incrementalData {
    if (receivedData ==nil) { receivedData = [[NSMutableData alloc] initWithCapacity:2048]; } 
    [receivedData appendData:incrementalData];
}
Redshank answered 20/2, 2012 at 15:22 Comment(10)
Ok, thanks. I did this, but it doesn't change anything :( And yes, I'm using some login/password to authenticate. Why?Dansby
is this in the simulator or on device?Redshank
Seeing as you are trying to access a local location, try accessing a non-local location, such as www.google.co.uk to test. Also put an nslog as the first line inside didReceiveResponse to see if it gets in there. btw, please share the url.Redshank
Still not working with google.com. And didReceiveResponse is never called. Tried to add a NSLog, but it never shows up.Dansby
I'm wondering if the problem isn't coming from the simulator in XCode 4.2. Because sometimes when I run the app, it works perfectly fine. But most of the time, it doesn't.Dansby
I've just tried it on a device. Still the same problem. The connection seems to be initiated (as I'm getting the message "Connection started", but then nothing happens.Dansby
Thanks for the tip. Tried it, but unfortunately, it doesn't fix my problem.Dansby
can you share the actual url in case it gives any hints to what the issue might be? also, try the online url google.com or similar over a 3g connection to rule out internal firewall issues.Redshank
Well, the URL is local, so it won't help : localhost/API/currencies/?type=json I tried using google.com, but same issue. On both Wifi and 3G.Dansby
I just created a new test project and added a stripped back version of your code (without authentication & base64) accessing google.com and it worked fine.Redshank
S
0

I think the problem will be with server side. Try to increase TimeoutInterval to 60 so there will be more time to fetch data from server. Didn't you get "connection timed out" message after 10 seconds?

EDIT

Hi, I think still you are not reached a solution. When I read the code in detail, I found some statements are confusing.

1) [request setValue:@"text/xml" forHTTPHeaderField:@"Accept"]; replace with

    [request setValue:@"text/plain" forHTTPHeaderField:@"Accept"];

Also include,

    [request setValue:@"text/plain" forHTTPHeaderField:@"Content-Type"];

And finally...

The error "connection timed out" indicates that the iPhone does not receiving any data from server. As soon as iPhone gets a bye of data it will call - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data. Try to put NSLog after each statements to verify variables hold desired value. Try to check the length of data --sourceData-- before sending ...

Sika answered 20/2, 2012 at 15:32 Comment(2)
I'm trying to reach a local URL. I tried with a 60s TimeoutInterval, but it doesn't work neither. If I try to access the same URL using Safari, it works perfectly fine. And the funny thing is that sometimes it just works. I'm wondering if the problem isn't coming from the simulator, or something.Dansby
I get the same issue as you Chris, very frustrating.Unsuspecting
P
0

Error message, as you have told in comments, is saying that the request has timed out. I am sure that if you remove the line with timeout, you will get either the same response or actual data, after 60 seconds. Make sure you wait enough, because if your connection is very weak for some reason, the request may not time out after 60 seconds because it keeps downloading data.

Is your app in foreground while you launch this? Make sure you don't suspend it.

Furthermore, you say that the server is online, but your code is timing out. Means something is probably wrong with your connection after all.

In another comment you say that sometimes it works. Even more points to the fact that the connection is weak/unreliable or breaking up.

Pinfeather answered 20/2, 2012 at 15:43 Comment(1)
As I've told in my post, I'm not using the timeout. I just tried it to see if my delegate methods were called, and they are. If I remove the timeout, or set it up to 60seconds, I'm still getting nothing. I'm using the simulator, and trying to reach a local server that I can reach in less than a second using Safari. And it's the same if I try to reach google.com or any website. And yes, my app is in foreground.Dansby
E
0

Some thoughts here:

  1. Please do not store passwords in UserDefaults, use the keychain for that (maybe you are only testing, I just wanted to have this mentioned)
  2. Why do you convert your NSURL url to a new NSURL by calling stringWithFormat: on the url? (Oh, I see @ade already mentioned that)
  3. Is this an ARC-enabled App? If not, your NSMutableData will be autoreleased too soon, use self.receivedData = [NSMutableData data] and you will see a crash.
  4. Try making your NSURLConnection an instance variable and hold on to it. I think it should work the way you do it right now, but I tend to hold on to it and never had the problem you mention here.
  5. Weird that your 10 seconds timeout seems to work, I had trouble getting this to work and found that on iPhone, the timeout can not be lower than 240 seconds. Yes, I was confused about this as well, but: https://mcmap.net/q/320215/-nsurlconnection-timeout
Edgy answered 20/2, 2012 at 18:28 Comment(2)
1. It's just for my testing, indeed. But I've never used the keychain so far. Do you have any good recommendation for that? 2. Yeah I know, stupid :) 3. Yes, ARC-enabled 4. Tried it. Doesn't fix it neither.Dansby
@Dansby Keychain handling only with Apple's methods is a pain, check out SFHFKeychainUtils: github.com/ldandersen/scifihifi-iphone/tree/master/securityEdgy

© 2022 - 2024 — McMap. All rights reserved.