NSURLConnection always failing after restarting app - ios

I realize this is a vague question, but I'm wondering if anyone else has observed this. Here is my code for calling the NSURLConnection
// Get data from server
NSString *host = #"www.hostname.com";
NSString *urlString = [NSString stringWithFormat:#"/theRestOfTheURL"];
NSURL *url = [[NSURL alloc] initWithScheme:#"http" host:host path:urlString];
DLog(#"URL is %#", url);
// Create the NSMutableData to hold the received data.
// receivedData is an instance variable declared elsewhere.
receivedData_ = [[NSMutableData data] retain];
NSURLRequest *theRequest=[NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:15.0];
// create the connection with the request
// and start loading the data
self.powerPlantDataConnection = [[[NSURLConnection alloc] initWithRequest:theRequest delegate:self] autorelease];
[url release];
When I first load the app it works fine, and I can call it repeatedly without any problem. But if I close the app and reopen it, the
(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
delegate method gets called every time, with a request timed out error message. I have two different view controllers where I am making calls to two different URLS, and both of them fail every time after closing and reopening the app.
Can anyone think of any reason why this might be happening? I'm not sure where to start looking. What could be the cause of a request timed out error? There should be nothing wrong with the request since it works when I first run the app.
Edited to add that it seems I only have this problem on my device, not on the simulator.

Wish you had shared some chrash log(especially with clear definition like
[error localizedDescription] class method..)
As you have said it is going to timeout(your request). and since your way of creating the objects is too messy, you make the work bigger for your system. I suggest using GCD when downloading data and especially in situations like yours, having different interfaces and urls..
A suggestion
You can create your url object like this:
NSURL *url = [NSURL urlWithString:[NSString stringWithFormat:#"http://%#/%#?key1=%#&key2=%#", yourDomain, targetFile, value1, value2]];

I switched over to using ASIHTTPRequest, which improved things but I would still get stuck in situations where I was getting timed out errors every time I tried to refresh. I looked and asked around, and eventually found that disabling calls to TestFlight solved my issue. More information here:
ASIHTTPRequest request times out
and here:
github.com/pokeb/asi-http-request/issues/320

Related

Random error on loading a static resource with a UIWebView

I'm using a UIWebView to load a static resource shipped within my application bundle. Sometimes, I have no clear what the problem could be, I receive the following error within the delegate method - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
NSUnderlyingError = "Error Domain=kCFErrorDomainCFNetwork Code=-1001
The resource is loaded through a NSURLRequest where I set up a timeout interval of 10 seconds, but that interval is not followed. In fact, in the debug console I'm able to see that the error delegate is called after about 2 seconds.
NSURL *htmlFile = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"root" ofType:#"html"] isDirectory:NO];
NSURLRequest* htmlRequest = [NSURLRequest requestWithURL:htmlFile cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10.0];
[webView loadRequest:htmlRequest];
The fact is that I cannot always replicate the problem I have. Any suggestions?
P.S. I'm working with an app that runs from 4.3. The problem is also with iOS 7.
According to apple CFNetwork Error Codes Reference this code is a timeout error:
kCFURLErrorTimedOut = -1001
Timeout are not always easy to reproduce most likely you should extend the timeout value when you init the NSURLRequest.
According to the same docs you can query the object for additional information.
For example:
if (CFEqual(CFErrorGetDomain(err), kCFErrorDomainCFNetwork) && CFErrorGetCode(err) == kCFHostErrorUnknown) {
CFDictionaryRef userInfo = CFErrorCopyUserInfo(err);
CFNumberRef number = (CFNumberRef) CFDictionaryGetValue(userInfo, kCFGetAddrInfoFailureKey);
...
CFRelease(userInfo);
}
I suppose that the resource you are looking for is not available. Be sure that the path is correct (ios is case sensitive) and if you are downloading some contents from internet be sure that the download is completed and the file is copied from the temporary folder to the final destination.

iOS large file download ~1GB files

For my bachelor thesis I have to implement an eLearning app for iOS. As you can see in my title, I have to download a file in the documents directory that has a size of nearly 1 or 2 GB. I'm very new at iOS-Development, so I would appreciate every tip how i can handle that.
Many thanks in advance!
Its good that you have read about NSURLConnection and ASIHTTP. But as you must be aware ASIHTTP is no longer actively developed/maintained. NSURLConnection is good to understand and learn the basics.
For day to day use, I'd suggest you use AFNetworking. It is simple to use and contains example for understanding how to use it.
For downloading large files it is recommended to write the downloaded data directly to a file rather than storing it in the memory. Using AFNetorking you can do this by,
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:#"download.zip" append:NO];
I have not tried downloading that large data myself, but I'm sure this will be a good start point for you.
AFNetworking: https://github.com/AFNetworking/AFNetworking
API documentation: http://cocoadocs.org/docsets/AFNetworking/2.0.0-RC2/
Happy coding!
Well, since this will very likely take a while to download I would definitely recommend doing this asynchronously using NSURLRequests and NSURLConnections.
My biggest concern though, is the pure size of this download and how this will likely not fit into RAM so this download may not actually be as easy as it seems. You can give it a shot, but what I would recommend is breaking this into multiple files/downloads if possible.
I will post code in a minute when I find code I have previously written.
Added Code
First off, make your class that needs to do the downloading to be an NSURLConnectionDelegate and `NSURLConnectionDataDelegate.
Then you can implement the download request as follows.
NSMutableData *linkData = [[NSMutableData alloc] init];
NSURLRequest *linkRequest = [[NSURLRequest alloc] initWithURL:youURL cachePolicy:NSURLRequestReloadRevalidatingCacheData timeoutInterval:10.0];
NSURLConnection *connect = [[NSURLConnection alloc] initWithRequest:linkRequest delegate:self];
The variable linkData should really be declared in the interface file and then allocated in the implementation, but for brevity I just created it as above.
Then you need the following methods which will be called
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[linkData appendData:data];
}
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
// handle a fail
}
-(void) connectionDidFinishLoading:(NSURLConnection *)connection {
// do what you need when download finishes
}

Using NSURLRequest+NSURLConnection seems overkill for a webcall with no data return

All,
This might seems very straightforward but I have already gone through the URL loading system program guide and the various NSURL.... classes and not found my answer.
I am just trying to do a simple call from the app to a website to reserve a party spot:
NSString *path=[NSString stringWithFormat:#"http://www.myparty123.com/ireservedURL.asp?Nickname=%#&Seat=%i&Email=%#&Currentparty=%i",john,5432,john#yahoo.com,6598];
NSURL* reservationURL =[NSURL URLWithString:path];
NSData *call= [NSData dataWithContentsOfURL:reservationURL];
This seemed to be the simple way but I get this warning that I am not using the "call" variable. And it seems overkill to do a call using NSData where there is no data return.
Yet, creating an NSURLRequest and initiating an NSURLConnection and then implementing delegates with that request seems to be overkill as well.
What am I missing.
Thanks
KMB
NSURLConnection has a method called sendSynchronousRequest:returningResponse:error: that allows you to download NSData from a URL without implementing the NSURLConnection delegate.
So your code could be rewritten:
NSString *path = [NSString stringWithFormat:#"http://www.myparty123.com/ireservedURL.asp?Nickname=%#&Seat=%i&Email=%#&Currentparty=%i",#"john",5432,#"john#yahoo.com",6598];
NSURL *url = [NSURL URLWithString:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
You'll no longer get the warning because you aren't assigning the data to a useless variable. If you want to know if the response was a success you could create a NSURLResponse variable and pass it into the sendSynchronousRequest method call.
Something to note is that this method will block whatever thread you call it on. So if you call this on the UI thread and the download takes 10 seconds the user will be unable to interact with the app. Implementing the NSURLConnection delegate or using the sendAsynchronousRequest:queue:completionHandler: method will not block the thread they are used on.
You could also wrap this code inside a NSInvocationOperation and add it to a NSOperationQueue or look into something like AFNetworking.
The simplest way to send a request as far as know is the + (id)stringWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding)enc error:(NSError **)errormethod of NSString

What are alternatives to NSURLConnection for chunked transfer encoding

I've checked for other questions relevant to this, but the only answer is "Use ASIHTTPRequest" as this is no longer being developed I wanted to ask what alternatives people are using, whilst working on our SDK I came across a lot of strange behaviour in NSURLConnection when receiving data from the server.
We tracked it down to the fact that NSURLConnection doesn't deal well with responses in chunked-encoding. Or at least so we read in this question here NSURLConnection and "chunked" transfer-coding
Some developers we were talking to say it gets better in iOS 5, we need to make sure that our SDK is backwards compatible with iOS 4.3 at least.
I want to confirm this is infact an issue in NSURLConnection, and how people are dealing with it.
All the alternatives I've found so far are based off of NSURLConnection and I'm assuming as such will have the same flaw. ASIHTTPRequest did in fact work because it's based a little lower than NSURLConnection, but were looking for alternatives in the knowledge it's no longer supported.
A list of other libraries looked at are:
Restkit,
ShareKit,
LRResty,
AFNetworking,
TTURLRequest
I'm aware there are similar questions here Is RESTKit a good replacement for ASIHTTPRequest? and here ASIHTTPRequest alternative But both of the solutions are based off NSURLConnection.
EDIT: I noticed I pointed to the wrong question at the start of my post, so thats updated. It points to a thread from 2008, and i've seen similar ones but none that are recent.
Chunked transfers are supported by NSURLConnection. I use them.
Define some props:
NSMutableData * responseData;
NSURLConnection * connection;
Establish a connection
NSURL *url = [NSURL URLWithString:#"...."];
self.responseData = [[NSMutableData alloc] initWithLength:0] ;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
Register your callback method for connection established
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
// You may have received an HTTP 200 here, or not...
[responseData setLength:0];
}
Register your callback method for "chunk received"
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSString* aStr = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"This is my first chunk %#", aStr);
}
Register your "connection finished" callback:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
}
And finally, register you "connection failed" callback:
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(#"Something went wrong...");
}
Just to chime in for the next person that gets here and still can't get NSURLConnection to work with chunk encoded data.
NSURLConnection will work with chunked encoding, but has non-disclosed internal behaviour such that it will buffer first 512 bytes before it opens the connection and let anything through IF Content-Type in the response header is "text/html", or "application/octet-stream". This pertains to iOS7 at least.
However it doesn't buffer the response if Content-Type is set to "text/json". So, whoever can't get chunked encoded NSURLConnection responses to work (i.e. callbacks aren't called) should check the response header and change it on the server to "text/json" if it doesn't break application behaviour in some other way.
There aren't any alternatives I'm aware of.
All the other libraries are built on top of NSURLConnection. Though you could use one of the non-iOS libraries, eg. libcurl.
ASIHTTPRequest is the only library I'm aware of that's built on top of the CFNetworking layer instead. This was (perhaps indirectly) the main reason the original developer stopped working on it - because it doesn't use NSURLConnection it has a lot of code.
It's probably not strictly correct to say that ASIHTTPRequest is no longer supported. It is true that the original developer no longer works on it, but if you look at the github commits you'll see it is still being worked on by other people. A lot of people still use it, for various reasons, myself included.
Having said all that, to go back to the problem you have: I'm not sure a 3 year old thread is necessarily a definitive reference to prove that a 1 year old release (ie. iOS 4.3) of NSURLConnection doesn't support chunked transfers. Chunked transfers are used so much on the web that it seems highly unlikely it would have a problem this large and obvious. It's possible there is something very particular to the server that you're using that is causing the issue.

How to purge / flush cache of NSString

Currently I am doing simple tests of my app (written in xCode for MAC OS X) and I noticed that there are some issues when it comes to getting data from internet. So I am requesting some text data:
NSString *dataFromInternet = [[NSString alloc] initWithContentsOfURL:url
usedEncoding:&encoding
error:&error];
Now:
If internet works then everything is awesome.
If internet disconnected then I am getting error in "error" however "dataFromInternet" still returns the very same data as if there was internet connect
If I request data (above code) while internet disconnected and then connect internet and request data once again, I am still getting error as if internet doesn't work!
I don't understand this behavior and what is going on. I can only guess there is some caching mechanism and I don't now how to fix it.
Please explain this ( #2 & #3 ) odd behavior and how to fix it.
Thank you.
Okay, so after sometime roaming around internet and trying to find answer to my question, here is what I came up with:
NSString *dataFromInternet = [[NSString alloc] initWithContentsOfURL:url
usedEncoding:&encoding
error:&error];
Above code does seem to use cache. In order to get data from internet and not to have all issues that are posted in the question, you have to use different object.
NSData* data = [[NSData alloc] initWithContentsOfURL:url options:NSUncachedRead error:&error];
NSString *dataFromInternet = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
What is happening in above sample code? You get data from internet almost the same way as you would with NSString except you specify following: "options:NSUncachedRead" - meaning that it will not cache the data and read always the latest and greatest - under condition that internet works.
Once you obtained data you can convert it into NSString if desirable. I needed NSString so I converted it back to what I want. Otherwise all of issue in original post are solved!
I can turn off airport on my mac and no data will be received and as soon as I turn on airport, data is flowing again. Very simple and works great for me.
Thank you.
So I'm not able to repro this. With this code:
NSError *error = nil;
NSStringEncoding encoding = 12345678; // known bad value
NSString *test = [[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:#"http://www.example.com/non-existant-page.html"] usedEncoding:&encoding error:&error];
if (test == nil) {
NSLog(#"didnt work:%#, enc=%d, error:%#",test, encoding, error);
} else {
NSLog(#"worked:%#, enc=%d, error:%#", test, encoding, error);
}
... and without internet, I get this:
2011-08-28 22:30:45.482 test[48578:207] didnt work:(null), enc=12345678, error:Error Domain=NSCocoaErrorDomain Code=256 "The operation couldn’t be completed. (Cocoa error 256.)" UserInfo=0x5b09280 {NSURL=http://www.example.com/non-existant-page.html}
I also ran this after doing it with internet to confirm that it wasn't being cached (it isn't), so I don't see how you could have gotten a result. Can you give us more of the code that you used?

Resources