Yet another "message sent to deallocated instance" - iphone

My app crashed (iOS/iPhone) after the execution of the following snippet:
NSHTTPURLResponse *urlResponse = nil;
NSError *error = [[NSError alloc] init];
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&error];
NSString *result = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
if ([urlResponse statusCode] ==500 ) {
...
}
} else {
NSLog(#"Response ==> status= %d", [urlResponse statusCode];
}
[result release];
[error release];
The code reached at the else statement, the statusCode is "0" and the code crashes with the
information that [CFError release] was sent to an deallocated instance. I commented out the
line [error release] and the crashed did not happen again. However we introduce a leak here.
What goes wrong with the error variable? Is it being used from sendSynchonousRequest?
What is the optimal way to resolve the problem?

The error object passed to an other method most not be initialized, the method you pass it on to will create the error object if an error accours. Since this method created the error object you are not the owner of that object and you are over releasing the error. The error object is created as autorelease.
Change :
NSError *error = [[NSError alloc] init];
to
NSError *error = nil;
and remove the
[error release];

Its is not necessary create error object. when you set the object to NSURLConnection, it automatic create autorelease error object. thats why your code crash, because there are also error release
try this:
NSHTTPURLResponse *urlResponse = nil;
NSError *error = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&error];
NSString *result = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
if ([urlResponse statusCode] ==500 ) {
...
}
} else {
NSLog(#"Response ==> status= %d", [urlResponse statusCode];
}
[result release];

Related

exception __NSarrayM objectforkey unrecognized selector sent to instance [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
i'm trying to make login page that get data fro php file by Json. it works fine until i use this sentence [jsonData objectForKey:#"state"] , an exception appears.
i tried to make another dictonary like some answers to question before. but nothing is working with me.
Output :
Response code : 200
Resonse ==> [{"state":"true"}]
JasonData ({state = true})
Then the exception
-[__NSarrayM objectforkey:]: unrecognized selector sent to instance
i'm new to objctive-C
if you could help me.
i will be greatfull
- (IBAction)loginClicked:(id)sender
{
#try
{
if([[txtUserName text] isEqualToString:#""] || [[txtPassword text] isEqualToString:#""] ) {
[self alertStatus:#"Please enter both Username and Password" :#"Login Failed!"];
} else {
NSString *post =[[NSString alloc] initWithFormat:#"username=%#&password=%#",[txtUserName text],[txtPassword text]];
NSLog(#"PostData: %#",post);
NSURL *url = [NSURL URLWithString:#"http://localhost/services/pages/login.php"];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSError *error = [[NSError alloc] init];
NSHTTPURLResponse *response = nil;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"Response code: %d", [response statusCode]);
if ([response statusCode] >=200 && [response statusCode] <300)
{
NSString *responseData = [[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
NSLog(#"Response ==> %#", responseData);
SBJsonParser *jsonParser = [SBJsonParser new];
NSDictionary *jsonData = (NSDictionary *) [jsonParser objectWithString:responseData error:nil];
NSLog(#"%#",jsonData);
NSLog(#"%#",[jsonData objectForKey:#"state"]);
NSString *state = [(NSString*) [jsonData objectForKey:#"state"] lowercaseString ];
NSLog(#"%#", state);
if([state isEqualToString:#"true"])
{
NSLog(#"Login SUCCESS");
[self alertStatus:#"Logged in Successfully." :#"Login Success!"];
}
else
{
NSString *error_msg = (NSString *) [jsonData objectForKey:#"error_message"];
[self alertStatus:error_msg :#"Login Failed!"];
}
}
else
{
if (error) NSLog(#"Error: %#", error);
[self alertStatus:#"Connection Failed" :#"Login Failed!"];
}
}
}
#catch (NSException * e)
{
NSLog(#"Exception: %#", e);
[self alertStatus:#"Login Failed." :#"Login Failed!"];
}
The JSON data returned by the webserive seems to be an NSArray and not NSDictionary. You can check that here,
id jsonData = [jsonParser objectWithString:responseData error:nil];
if([jsonData isKindOfClass:[NSDictionary class]]) {
NSLog(#"Dictionary");
}
else if([jsonData isKindOfClass:[NSArray class]]) {
NSLog(#"Array");
}
Your code crashes because you are assuming the parsed response as NSDictionary and passing the objectForKey: method. Being an NSArray it cannot recognise this method and raises an exception.
Now if it is an NSArray with one dictionary inside, you can read it as below,
[[jsonData objectAtIndex:0] objectForKey:#"state"];
Hope that helps!

Translation using Google Api

this is the code i am using to translate from English to Vietnamese.
NSString *urlPath = [NSString stringWithFormat:#"/translate_a/t?client=t&text=%#&langpair=en|vi",txt_view.text];
NSURL *url = [[NSURL alloc] initWithScheme:#"http"
host:#"translate.google.com"
path:urlPath];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"GET"];
NSURLResponse *response;
NSError *error;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if(error == nil)
{
NSString *result = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"Result : %#", result);
NSArray *arr = [api tocanizeTheString:result tocan:#","];
result = [arr objectAtIndex:0];
result = [api replaceStringwithString:result strTobeReplaced:#"[" stringReplaceWith:#""];
result = [api replaceStringwithString:result strTobeReplaced:#"\"" stringReplaceWith:#""];
txt_view.text = result; // here i get only translated data...
}
else
{
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
some times it give accurate result and sometimes it doesn't. please tell me whats the problem.
"My name is Taimur Mushtaq" i type this in my app, it shows correct result which is "Tên tôi là Taimur Mushtaq".
"I am a good boy" the result should be "Tôi là một chàng trai tốt". instead it is "tôi là m\u1ED9t c\u1EADu bé t\u1ED1t"

Why did the release statement here crashes the app?

NSError *theError = nil;
NSArray *keys = [NSArray arrayWithObjects:#"password", #"userId", nil];
NSArray *objects = [NSArray arrayWithObjects:passwordTextField.text, userNameTextField.text, nil];
NSDictionary *requestDictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
NSString *JSONString =[requestDictionary JSONRepresentation];
NSData *JSONData =[JSONString dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"JSONString :%#", JSONString);
NSLog(#"JSONData :%#", JSONData);
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://153.20.32.74/11AprP306/passenger/jsonitem"]];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:JSONData];
[request setHTTPMethod:#"POST"];
NSURLResponse *theResponse =[[NSURLResponse alloc]init];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&theResponse error:&theError];
NSLog(#"response : %#", theResponse);
NSLog(#"error : %#", theError);
NSLog(#"data : %#", data);
NSMutableString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"string: %#", string);
[string release];
//[theResponse release]; // this statement crashes the app
Has it got something with to do with this statement :NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&theResponse error:&theError];
I see a & symbol used. What does it means?
I'll post this as a new answer as you edited your question.
You are doing it the wrong way.
It is the responsability of sendSynchronousRequest:returningResponse:error: to create the response for you (or the error if something went wrong)
This is why you need to pass a pointer to theResponse and a pointer to theError
When the call to sendSynchronousRequest:returningResponse:error: is done, theResponse will be created and most importantly autoreleased (by sendSynchronousRequest:returningResponse:error) !!
So in the end you are back to the autorelease/over release issue.
The correct code is:
NSURLResponse *theResponse = nil; // no need to init it will be done later on
NSError *theError = nil; // no need to init either
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&theResponse
error:&theError];
if (aError != nil) { } // handle error
else {} // handle your response data
//no need to release theResponse
Well, you autorelease theResponse when you instantiate it, so releasing it twice is causing your problem. Either don't make the autorelease call or don't make the release call.
Personally, I'd get rid of the autorelease. release gives finer-grained control over the run of your program.
Oh, and the & there is nothing to worry about -- it just passes the address of the variable it proceeds. In this case, you need to pas an NSURLResponse**. Since you have an NSURLResponse*, you pass a reference to it.
This is because theResponse has sent the message autorelease in:
NSURLResponse *theResponse =[[[NSURLResponse alloc]init] autorelease];
If you release an object that has been autoreleased you will cause your application to crash for the Garbage Collector will over release the object.
The & simply means "give me the address of theError and theResponse (basically you are passing a pointer of pointer which is required by the method sendSynchronousRequest:returningResponse:error:)
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request
returningResponse:(NSURLResponse **)response
error:(NSError **)error
The NSURLResponse ** and NSError ** means 'address of address' so give them only theError or theResponse (without the &) would simply give the method 'their address' when it is expecting something else.

How to know if data is present in url are not

I have written code like this but I can't understand how to find if the data is present or not in the URL. Can anyone help me in solving this problem?
Note: This code terminates when the loop is entering the second condition. That is where it's terminating.
-(void)getdetails
{
NSLog(#"in get details");
NSURL *jsonurl=[NSURL URLWithString:#"http://www.myappdemo.com/checkout/services/getonlineusers.php"];
NSMutableURLRequest *request=[[[NSMutableURLRequest alloc]init ]autorelease];
[request setURL:jsonurl];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
NSError *error;
NSURLResponse *response;
NSData *serverReply = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *replyString = [[NSString alloc] initWithBytes:[serverReply bytes] length:[serverReply length] encoding: NSASCIIStringEncoding];
if([replyString isEqualToString:#"Invalid."]){ // i have not set the php code to output "invalid" so this will not work for now ...
NSLog(#"%#",replyString);
}
else {
NSMutableArray *tempArray =[replyString JSONValue];
int count=0;
self.temparray=tempArray;
for(int i=0;i<[tempArray count];i++)
{
///////Here in this loop when it is entering it is terminating /////////
NSDictionary *dict=[tempArray objectAtIndex:i];
NSLog(#"DICT is %#",dict);
NSString *string=[dict objectForKey:#"profilepic"];
NSURL *finalURL = [NSURL URLWithString:[string stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
NSLog(#"encoding string is %#",finalURL);
NSURL *url=[NSURL URLWithString:string];
NSString *source = [NSString stringWithContentsOfURL:finalURL encoding:NSUTF8StringEncoding error:nil];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:url];
NSLog(#"url is %#",url);
NSData *data=[NSData dataWithContentsOfURL:url];
if(!(data==nil))
{
NSLog(#"data is there");
UIImage *image=[[UIImage alloc]initWithData:data];
[self.array addObject:image];
[image release];
}
else {
/*
NSLog(#"if data is null condition block");
UIImage *image=[[UIImage alloc]init];
[self.array addObject:image];
[image release];
*/
}
count=count+1;
NSLog(#"count is %d",count);
}
}
[replyString release];
}
Where does the app terminate and what is the exception? Have you stepped through to see what the array object looks like during each iteration? Is it failing at NSData initWithContentsOfURL? Why don't you issue that as a separate synchronous request and test to see if you got a response?
Regarding your first (and any subsequent) synchronous request, it would probably be good to add a check to ensure you received a valid response (sorry for the formatting, the code tag isn't playing nicely at the moment)
if (response!=nil) {if([response isKindOfClass:[NSHTTPURLResponse class]]) {
// you have a valid response }}

NSHTTPURLResponse

Hey everbody, i'm trying to treat the response of a http post.
My php is giving a simple message, so, how can i treat it?
I mean, if gives me the "Error" message, do something, or "OK" do another thing.
NSHTTPURLResponse* urlResponse = nil;
NSError *error = [[NSError alloc] init];
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&error];
NSString *result = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"Response Code: %d", [urlResponse statusCode]);
if ([urlResponse statusCode] >= 200 && [urlResponse statusCode] < 300) {
NSLog(#"Response: %#", result);
}
if (result == #"Logged") {
NSLog(#"OK");
}
if (result == #"Error") {
NSLog(#"No");
}
Thanks!
Try the isEqualToString: method. E.g.:
if ([result isEqualToString:#"Logged"]) {
NSLog(#"OK");
} else if ([result isEqualToString:#"Error"]) {
NSLog(#"No");
}