Message sent to deallocated instance in iPhone - iphone

I am new to iPhone,
I am creating NSURLConnection as suggested by apple here
but my app crashes when i Dismiss my view, i have tried concept of NSZombieEnabled which shows me -[CALayer release]: message sent to deallocated instance 0x68b8f40
I am displaying a webpage in Webview, When users clicks on download link in the webview then shouldStartLoadWithRequest method will be called inside this method i am creating NSURLConnection.
here is my code snippet,
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data1
{
[receivedData appendData:data1];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Succeeded! Received %d bytes of data",[receivedData length]);
DirPath=[self applicationDocumentsDirectory];
NSLog(#"DirPath=%#",DirPath);
[receivedData writeToFile:DirPath atomically:YES];
UIAlertView* Alert = [[UIAlertView alloc] initWithTitle:#"Download Complete !"
message:nil delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[Alert show];
[Alert release];
// release the connection, and the data object
[connection release];
[receivedData release];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error1
{
[connection release];
[receivedData release];
// inform the user
NSLog(#"Connection failed! Error - %# %#",
[error1 localizedDescription],
[[error1 userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
//CAPTURE USER LINK-CLICK.
Durl=[[url absoluteString]copy];
//Checking for Duplicate .FILE at downloaded path....
BOOL success =[[NSFileManager defaultManager] fileExistsAtPath:path];
lastPath=[[url lastPathComponent] copy];
if (success) //if duplicate file found...
{
UIAlertView* Alert = [[UIAlertView alloc] initWithTitle:#"This FILE is already present in Library."
message:#"Do you want to Downlaod again ?" delegate:self
cancelButtonTitle:nil
otherButtonTitles:#"Yes",#"No",nil];
[Alert show];
[Alert release];
}
else //if duplicate file not found directly start download...
{
// Create the request.
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:Durl]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// create the connection with the request and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
// Create the NSMutableData to hold the received data.
receivedData = [[NSMutableData data] retain];
} else {
NSLog(#"Inform the user that the connection failed.");
}
return YES;
}
Any help will be appreciated.

Make sure that in your implementation of dealloc you are resetting the delegate to nil. Another place for doing so would be viewWillDisappear:.
The reason for your app to crash / access a zombie is that the UIWebView instance will possibly be trying to call back the viewController even though it has already been deallocated. To prevent that, you have to set the delegate of that UIWebView back to nil before the viewController goes out of scope. That is a general issue when working with delegation prior to iOS5's ARC implementation. iOS5 finally offers weak references, those actually nil themselves once their instance is getting deallocated.
Example A:
- (void)dealloc
{
[...]
_webView.delegate = nil;
}
Example B:
- (void)viewWillDisappaer:(BOOL)animated
{
[super viewWillDisappaer:animated];
_webView.delegate = nil;
}
Edit:
After reading your question once again, I realised that the zombie is a UIView or a UIControl since the message is sent to a CALayer. Make sure your problem actually is related to the web view by temporarily removing all webView related code.

I think issue with this NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
You are creating an instance of NSURLConnection with delegate self, when you dismiss the view everything get deallocated on that view. But when the NSURLConnection tries to call it's delegate method crash will occur.
So you need to set the delegate of NSURLConnection to nil in your viewWillDisappear for doing this, you need to create object of NSURLConnection in interface.
#interface yourClass
{
NSURLConnection *theConnection;
}
#end
in .m
theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
- (void)viewWillDisappaer:(BOOL)animated
{
[super viewWillDisappaer:animated];
theConnection.delegate = nil;
}

Related

Second asynchronous NSURLConnection doesn't call delegate methods

From my ApplicationDelegate, I'm doing an NSURLConnection fetch over the network (it's wrapped in a class, as you'll see below). This one seems to work correctly: I get all the data in didReceiveData and I get the completion call connectionDidFinishLoading. At the end of connectionDidFinishLoading, I instantiate one or more of a slightly different kind of wrapper class, but they're essentially the same thing. The problem is that the second NSURLConnection's delegate is never having it's methods called.
I've looked at many different answers, but all to no avail. I'm not spawning any new threads and all the [NSThread isMainThread] checks I've littered throughout the code return true.
I'm stumped. Can anyone help me out? Here's the relevant code:
App Delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
ConnectionWrapper* w = [[ConnectionWrapper alloc] initWithParams:self
url:[NSURL URLWithString:<url>]];
[w beginFetch];
return YES;
}
...
-(void)fetchCompleted:(NSURL*)url directory:(NSString*)directory
{
NSLog(#"fetch completed");
}
-(void)fetchFailed:(NSURL*)url
{
NSLog(#"fetch failed");
}
...
ConnectionWrapper:
-(id)initWithParams:(id<ConnectionWrapperDelegate>)d url:(NSURL*)url
{
delegate = d;
connURL = url;
return [self init];
}
-(void)beginFetch
{
NSURLRequest* request = [[NSURLRequest alloc] initWithURL:connURL];
NSURLConnection* conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[conn release];
[request release];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(#"append");
[responseData appendData:data];
}
- (void) connectionDidFinishLoading: (NSURLConnection*) connection
{
... parsing ....
DifferentConnectionWrapper* w = [[DifferentConnectionWrapper alloc] initWithParams:self
url:[NSURL URLWithString:<different url>]];
[w beginFetch];
}
-(void)fetchCompleted:(NSURL*)URL
{
NSLog(#"completed: %#", URL);
}
-(void)fetchFailed:(NSURL*)URL
{
NSLog(#"failed");
}
DifferentConnectionWrapper:
-(id)initWithParams:(id)d url:(NSURL*)url
{
delegate = d;
connURL = url;
return [self init];
}
-(void)beginFetch
{
NSURLRequest* request = [[NSURLRequest alloc] initWithURL:connURL];
NSURLConnection* conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[conn release];
[request release];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(#"append");
[responseData appendData:data];
}
- (void) connectionDidFinishLoading: (NSURLConnection*) connection
{
... parsing ....
DifferentConnectionWrapper* w = [[DifferentConnectionWrapper alloc] initWithParams:self
url:[NSURL URLWithString:<different url>]];
[w beginFetch];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(#"got response");
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(#"got data");
[responseData appendData:data];
}
- (void) connectionDidFinishLoading: (NSURLConnection*) connection
{
NSLog(#"image saver completed: %#", connURL);
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"error");
}
ConnectionWrapper and DifferentConnectionWrapper have similar functions, but there's other logic that I've omitted here for brevity.
thanks for the help. I appreciate it.
A couple of things: I don't see a didFailWithError: in your first wrapper class, and (a little off topic) are you leaking memory with your DifferentConnectionWrapper *w ?
Anyway, what I would try is: see if you can invoke DifferentConnectionWrapper directly from the appDelegate instead of the ConnectionWrapper.
And I would try to decouple the two calls in any event. When the first one finishes, and calls appDelegate, can't you launch your DifferentConnectionWrapper from there?
I realize this doesn't explain your problem, but you might get it working (and which of THOSE two things is more important, is an entirely different debate.)
I believe the problem is that you’re releasing the URL connection in -beginFetch:
-(void)beginFetch
{
NSURLRequest* request = [[NSURLRequest alloc] initWithURL:connURL];
NSURLConnection* conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[conn release];
[request release];
}
The URL connection object should be kept alive and released when the connection has finished loading:
- (void) connectionDidFinishLoading: (NSURLConnection*) connection
{
... parsing ....
// *** Release the connection and whatever data you’ve kept related to
// this particular connection
[connection release];
[responseData release];
// *** or [responseData setLenght:0]; depending on how you’re
// managing responseData
DifferentConnectionWrapper* w = [[DifferentConnectionWrapper alloc] initWithParams:self
url:[NSURL URLWithString:<different url>]];
[w beginFetch];
}
or when there’s been an error:
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
// *** Release the connection and whatever data you’ve kept related to
// this particular connection
[connection release];
[responseData release];
// *** or [responseData setLenght:0]; depending on how you’re
// managing responseData
// inform the user
NSLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
Edit: Your initialiser is a tad weird:
-(id)initWithParams:(id<ConnectionWrapperDelegate>)d url:(NSURL*)url
{
delegate = d;
connURL = url;
return [self init];
}
There’s no way to know what happens unless we see the code for -init and, at any rate, this should be the designated initialiser, so it shouldn’t be sending -init to self anyway. Furthermore, you should be retaining the url object that’s being passed to the initialiser.
The following makes more sense:
-(id)initWithParams:(id<ConnectionWrapperDelegate>)d url:(NSURL*)url
{
self = [super init];
if (self) {
delegate = d;
connURL = [url retain];
}
return self;
}
Don’t forget to release the url object in -dealloc or when you’re assigning another value to connURL.
OK. It turns out that this bug was caused by something I missed. I was going into a hard spin right after that second request, which would probably screw up just about anything. Once I fixed that problem, everything worked just fine.
Thanks for the help.

XCode webview connection/server error handling

All,
I am fairly new to XCode and am trying to get a handle on how to best deal with connection issues when trying to use a WebView. I know there are related questions on SO, but none seem to offer complete solutions. I have the following code, but it seems a little inefficient. Hopefully, someone can help me refactor it down to a point where it can be usable anywhere that a UIWebView is called.
NOTE: Please ignore memory issues for now. I realize that has to be added as well.
- (void)viewDidLoad {
[webView setDelegate:self];
NSString *urlAddress = #"http://www.somesite.com/somepage";
NSURL *url = [NSURL URLWithString:urlAddress];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
NSURLConnection *urlConnection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
[super viewDidLoad];
}
// Check for URLConnection failure
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
UIAlertView *connectionError = [[UIAlertView alloc] initWithTitle:#"Connection error" message:#"Error connecting to page. Please check your 3G and/or Wifi settings." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[connectionError show];
webView.hidden = true;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
//Check for server error
if ([httpResponse statusCode] >= 400) {
UIAlertView *serverError = [[UIAlertView alloc] initWithTitle:#"Server error" message:#"Error connecting to page. If error persists, please contact support." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[serverError show];
webView.hidden = true;
//Otherwise load webView
} else {
// Redundant code
NSString *urlAddress = #"http://somesite.com/somepage";
NSURL *url = [NSURL URLWithString:urlAddress];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[webView loadRequest:urlRequest];
webView.hidden = false;
}
}
// Seems redundant since we are already checking the URLConnection
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
UIAlertView *connectionError = [[UIAlertView alloc] initWithTitle:#"Connection error" message:#"Error connecting to page. Please check your 3G and/or Wifi settings." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[connectionError show];
}
I guess what I'm wondering is, are there any shortcuts to achieve the desired functionality? Can I somehow access the URLResponse via the WebView directly? Does a nil value for the URLConnection or UIWebView imply connection errors without having to explicitly check for them? Is there an easier way to pass the URLRequest down into the delegate methods so it doesn't have be recreated twice?
Thanks in advance!
- (void)viewDidLoad {
webView = [[UIWebView alloc]init];
[webView setDelegate:self];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://yourUrl.com"]]]
[super viewDidLoad];
}
#pragma mark UIWebView delegate methods
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
//read your request here
//before the webview will load your request
return YES;
}
- (void)webViewDidStartLoad:(UIWebView *)webView{
//access your request
webView.request;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView{
//access your request
webView.request;
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
NSLog(#"could not load the website caused by error: %#", error);
}
-(void)dealloc{
[webView release];
[super dealloc];
}
You can load the webpage with NSURLRequest directly into your webview. With the delegate callback methods you can change the behavior of your webview.
With this piece of code you should get it done.

NSURLConnection doesn't call didRecieveData method

I want my application to download some data from the internet, in iPhone SDK documentation
i found NSURLConnection class, which is used for downloading, Am i right?
I wrote the same code as it is in the documentation and ran it. Connection was created successfully, but no data were downloaded. connectionDidFinishLoading is fired after sec or two but with no data in result. Problem is, that didRecieveData method is never fired. I dont know why, i searched the internet, but every result was the same code as it is in the documentation. Could you give an advice please? Thanks for every reply
My downloader class source code is below.
Downloader.h
#interface Downloader : NSObject {
NSURLConnection *conn;
//Array to hold recieved data
NSMutableData *recievedData;
}
#property (nonatomic, retain) NSURLConnection *conn;
#property (nonatomic, retain) NSMutableData *recievedData;
- (void)downloadContentsOfUrl:(NSURL *)url;
#end
Downloader.m
#import "Downloader.h"
#implementation Downloader
#synthesize recievedData, conn;
- (void)connection:(NSURLConnection *)connection didRecieveResponse:(NSURLResponse *)response
{
NSLog(#"did recieve response");
[recievedData release];
recievedData = nil;
}
- (void)connection:(NSURLConnection *)connection didRecieveData:(NSData *)data
{
NSLog(#"did recieve data");
//Append the new data to the recieved data
[recievedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
//Release the connection and the data object
[connection release];
[recievedData release];
NSLog(#"Connection failed! Error - %# %#", [error localizedDescription],
[[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//ToDo with data
//[recievedData writeToFile:#"data" atomically:YES];
NSLog(#"downloaded");
NSLog(#"%u", [recievedData length]);
//Release the connection and the data object
[connection release];
[recievedData release];
}
- (void)downloadContentsOfUrl:(NSURL *)url
{
//Create the connection
//Create the request
NSURLRequest *urlRequest = [[NSURLRequest alloc] initWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
//Create the connection with the request and start loading the data
conn = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self
startImmediately:YES];
if(conn)
{
//Create the NSMutableData that will hold the recieve data
recievedData = [[NSMutableData data] retain];
NSLog(#"Connection success!");
}
else
{
NSLog(#"Can't download this file!");
}
}
- (void)dealloc
{
[conn release];
[recievedData release];
[super dealloc];
}
You've misspelt "receive":
// Your signature
- (void)connection:(NSURLConnection *)connection didRecieveData:(NSData *)data;
// Correct signature
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
You have a typo in the name of your didReceiveData method (i before e, except after c :-)
Thus it will look like your class doesn't implement that (optional) selector and it will be silently ignored.

Need help: My program should react when an other class is doing something specific - Not as easy as it sounds

I´m writing an program that uses twitter. I want that my app shows an UIAlertView when the user presses on the "Tweet"-Button and the username or password is wrong.
For my Twitterfunction I use the TwitterRequest.m/h from Brandon Trebitowski. If everthing works great and the username/password is right, this happens in my app:
TwitterRequest * t = [[TwitterRequest alloc] init];
(...);
[t statuses_update:twittermessage.text delegate:self requestSelector:#selector(status_updateCallback:)];
loadingActionSheet = [[UIActionSheet alloc] initWithTitle:#"Posting to Twitter..." delegate:nil
cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
[loadingActionSheet showInView:self.view];
}
- (void) status_updateCallback: (NSData *) content {
[loadingActionSheet dismissWithClickedButtonIndex:0 animated:YES];
[loadingActionSheet release];
NSLog(#"%#",[[NSString alloc] initWithData:content encoding:NSASCIIStringEncoding]);
}
But how can I show an UIAlertView when the username/password was wrong?
Here is the TwitterRequest.m:
#import "TwitterRequest.h"
#implementation TwitterRequest
#synthesize username;
#synthesize password;
#synthesize receivedData;
#synthesize delegate;
#synthesize callback;
#synthesize errorCallback;
-(void)friends_timeline:(id)requestDelegate requestSelector:(SEL)requestSelector{
isPost = NO;
// Set the delegate and selector
self.delegate = requestDelegate;
self.callback = requestSelector;
// The URL of the Twitter Request we intend to send
NSURL *url = [NSURL URLWithString:#"http://twitter.com/statuses/friends_timeline.xml"];
[self request:url];
}
-(void)statuses_update:(NSString *)status delegate:(id)requestDelegate requestSelector:(SEL)requestSelector; {
isPost = YES;
// Set the delegate and selector
self.delegate = requestDelegate;
self.callback = requestSelector;
// The URL of the Twitter Request we intend to send
NSURL *url = [NSURL URLWithString:#"http://twitter.com/statuses/update.xml"];
requestBody = [NSString stringWithFormat:#"status=%#",status];
[self request:url];
}
-(void)request:(NSURL *) url {
theRequest = [[NSMutableURLRequest alloc] initWithURL:url];
if(isPost) {
NSLog(#"ispost");
[theRequest setHTTPMethod:#"POST"];
[theRequest setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[theRequest setHTTPBody:[requestBody dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]];
[theRequest setValue:[NSString stringWithFormat:#"%d",[requestBody length] ] forHTTPHeaderField:#"Content-Length"];
}
theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
// Create the NSMutableData that will hold
// the received data
// receivedData is declared as a method instance elsewhere
receivedData=[[NSMutableData data] retain];
} else {
// inform the user that the download could not be made
}
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
//NSLog(#"challenged %#",[challenge proposedCredential] );
if ([challenge previousFailureCount] == 0) {
NSURLCredential *newCredential;
newCredential=[NSURLCredential credentialWithUser:[self username]
password:[self password]
persistence:NSURLCredentialPersistenceNone];
[[challenge sender] useCredential:newCredential
forAuthenticationChallenge:challenge];
} else {
[[challenge sender] cancelAuthenticationChallenge:challenge];
// inform the user that the user name and password
// in the preferences are incorrect
NSLog(#"Invalid Username or Password"); //THIS MUST be important. The console shows this message, if the username/password is wrong. Here is also the place, where I set the bool to TRUE
}
}
- (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 declared as a method instance elsewhere
//[receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
//NSLog([[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
// append the new data to the receivedData
// receivedData is declared as a method instance elsewhere
[receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
// release the connection, and the data object
[connection release];
// receivedData is declared as a method instance elsewhere
[receivedData release];
[theRequest release];
// inform the user
NSLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
if(errorCallback) {
[delegate performSelector:errorCallback withObject:error];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// do something with the data
if(delegate && callback) {
if([delegate respondsToSelector:self.callback]) {
[delegate performSelector:self.callback withObject:receivedData];
} else {
NSLog(#"No response from delegate");
}
}
// release the connection, and the data object
[theConnection release];
[receivedData release];
[theRequest release];
}
-(void) dealloc {
[super dealloc];
}
#end
I know that the important line in the TwitterRequest.m is in the else-cause of the -(void)connection-methode, because the Console writes always Invalid Username or Password, when they are wrong. So I tried to make there a bool as propertey, which will be set to TRUE, when the name/password is wrong(= when the else-cause will be used). In my ViewController I made this:
if (t.stimmtNicht == TRUE) {
[loadingActionSheet dismissWithClickedButtonIndex:0 animated:YES];
[loadingActionSheet release];
UIAlertView *alert;
alert = [[UIAlertView alloc] initWithTitle:#"Ouch!"
message:#"Your Username or Password is wrong!"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[alert show];
[alert release];
}
But he always doesn't use the if-cause, even if the password is wrong. I think the code go faster through the if-quere than the TwitterRequest set it to TRUE. What can I do?
Thanks for your help and sorry for this stupid question, but I'm learning Objective-C and programming in general since just one week and I don´t know correctly how to interact from my ViewController with other classes.
Also sorry for my bad English!
Two ways I can think of:
Apparently your TwitterRequest class has a "delegate" ivar; try calling the delegate to tell him (her?) that your credentials are wrong.
Send an NSNotification through the NSNotificationCenter
In both cases, the class who gets notified should display the login view (with the username and password fields), and that's it.

Question about HTTP exception handling on iPhone

I try to add a method to handle exception, but the program just crashes instead of pop up an AlertView.
1) I set up the connection:
-(void)connect:(NSString *)strURL
{
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:strURL]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection)
{
// receivedData is declared as a method instance elsewhere
receivedData = [[NSMutableData data] retain];
}
else
{
// inform the user that the download could not be made
}
}
2)I add method to receive data and conver it to string:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// append the new data to the receivedData
// receivedData is declared as a method instance elsewhere
[receivedData appendData:data];
ReturnStr = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
}
3)I add exception handle method:
-(void) connection:(NSURLConnection *)connection didFailWithError: (NSError *)error {
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle: [error localizedDescription]
message: [error localizedFailureReason]
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[errorAlert show];
}
After I change the strURL to a wrong url, the program just crashes. Any ideas why the AlertView doesn't pop up?
Check out the error handling that I've got in this file. If you set the URL to an invalid URL, it does (in my example) come back with a nice dialog error message. I just tried it to be sure.
Relevant code in the linked file is:
-(void) connection:(NSURLConnection *)connection
didFailWithError: (NSError *)error {
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle: [error localizedDescription]
message: [error localizedFailureReason]
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[errorAlert show];
[errorAlert release];
[activityIndicator stopAnimating];
NSLog (#"Connection Failed with Error");
}