So for the past two days I’ve had my iPhone app crashing and vomiting “EXC_BAD_ACCESS” in the console. Generally speaking, this error means you’ve released a reference to some object you still need and some other object tried to send a message to said object afterward. It turns out that it was entirely my fault and (GASP) paying a little more attention to Apple’s reference would saved hours and hours of debugging for me.
NSURLConnection is actually pretty simple to use but here are some tips:
- Use the asynchronous mode for any reasonably large file (bigger than a few KB) as people might be on a slow Edge network connection and locking up the view is never a good thing.
- Do not send the message “start” to your connection if you use connectionWithRequest or initWithRequest to initialize your connection as you’ll get the nasty “EXC_BAD_ACCESS” error mentioned above. The reason for this is simple: You’ve scheduled your connection to time out in n seconds, the method that initializes the connection starts fetching data immediately. You then send the message “start,” which spins off the connection trying to fetch data again. This works fine except that the original attempt eventually times out and tries to call back, hosing everything over and crashing your application hard core. Oops. You should only send the message “start” to your connection if you initialize it with initWithRequest:delegate:startImmediately.
- When setting up NSURLRequest to pass to NSURLConnection, I highly recommend using NSMutableURLRequest so you can set the User-Agent header. Some http servers may not return data, even for a simple GET without the User-Agent. It’s my understanding that User-Agents are optional, but I do not know if said server behavior is nonstandard.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString: @"http://myurl.com"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15.0];
//Borrow FF2’s User-Agent
[request setValue: @"Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.16) Gecko/20080702 Firefox/2.0.0.16" forHTTPHeaderField: @"User-Agent"];
I hope this saves someone some time.
Thanks! You’ve probably saved me hours of debugging. Sending ’start’ was exactly the mistake I made too.
Thank you so much! This probably saved me another day of debugging (after one already wasted) – The documentation should really be more explicit regarding the ’start’ method.
FFS thank you. Argh that was killing hours of my time. Bloody lame docs Apple.
Thank you, thank you, thank you. This finally explains my issue! And I always wondered where the crashes come from. However, I must say that the docs are pretty poor. Just saying
“Returns an initialized URL connection and begins to load the data for the URL request.”
is too little IMHO. It should state
“This method has the same effect as calling initWithRequest:delegate:startImmediately: and setting startImmediatly parameter to YES”
I would say this is actually a bug in the framework. It should not allow a download to be started twice using the same memory reference?
Thank you so much! Hours already lost, but many more saved, I’m sure.
Life saver. I was tearing my hair out trying to figure this one out – many thanks.
I’m still getting the EXC_BAD_ACCESS error with the following code:
NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
[con start];
.. what gives?
Try wrapping a retain or autorelease around the initialization of your connection. Did that work?