Memory leak when parse JSON string using SBJSON - iphone

I am using following code to parse JSON and getting memory leak (100%) on line number 2. I don't know what is the problem, can someone help me ?
NSString *response = [request responseString];
NSMutableDictionary *responseJSON = [response JSONValue]; (100% leak)
NSString *tockenString = [responseJSON objectForKey:#"Token"];
NSString *userIDString = [responseJSON objectForKey:#"ID"];

I found the answer. Go to SBJsonParser.m function scanRestOfString and change the line
from
*o = [[NSMutableString alloc] initWithBytes:(char*)c length:len encoding:NSUTF8StringEncoding];
to
*o = [[[NSMutableString alloc] initWithBytes:(char*)c length:len encoding:NSUTF8StringEncoding] autorelease];
SBJsonParser has a like in scanRestOfString/NSMutableString. I reported the bug as well. Thank you all.

Remove those 2 autoreleases. They overrelease the objects.

I've had a similar problem but it turned out the leak was actually higher in the chain of methods, but Instruments was (mistakenly) pointing to this line. Look at the methods that store the results retrieved from this code.

Related

iPhone: strange output when casting nsdata to nsstring

I get a NSData object in return after decrypting a payload with aes128:
NSData *returnData = [ciphertext AES128DecryptWithKey:keyData withIV:ivData];
I get the following hex output when i try to NSLog this:
<2db88b73 d84599a1 5779c736 09c975b7 92750cf2 d11cb41b 19f13781
4401bc57 b2ad96c8 402e3ccf 851c0219 00aec76b>
I then try to setting it as NSString:
[[NSString alloc] initWithData:returnData
encoding:NSUTF8StringEncoding];
When using NSLog() on the string i get "(null)" as output.
Can someone tell me why and where i should look for the problem?
Collided with the same issue some time ago, found the answer here.
If the data is not null-terminated, you should use -initWithData:encoding:
NSString* newStr = [[[NSString alloc] initWithData:theData
encoding:NSUTF8StringEncoding] autorelease];
If the data is null-terminated, you should instead use -stringWithUTF8String: to avoid the extra \0 at the end.
NSString* newStr = [NSString stringWithUTF8String:[theData bytes]];
(If you have ARC enabled, remove the -autorelease call.)

How to Convert NSData to NSString

I know this has been asked quite before, and I already followed couple of approaches, but they don't work.
Following is what I already tried:
NSString *newStr = [NSString stringWithUTF8String:[responseData bytes]];
NSString *newStr = [NSString stringWithFormat:#"%.*s", [responseData length], [responseData bytes]];
None of them works. In 1st case, it fills newStr with null. In 2nd, it fills with junk characters. I know from debugger log (po responseData) that I get valid response which is like bbbbbb 00 bbbbbb. [server sends them as byte array]
What to do?
EDIT:
I am receiving this data from http request response - using ASIHTTPRequest library, in case anybody can help on that line.
Try this,
NSData *responseData; [Initialize it]
NSString *receivedDataString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"%#",receivedDataString);
Please try following code
NSString *string = [[[NSString alloc] initWithData: responseData.bytes encoding:NSUTF8StringEncoding] autorelease];
You can use this code lines
NSString *str=[[NSString alloc] initWithBytes:data1.bytes length:data1.length encoding:NSUTF8StringEncoding];
I am posting this for records sake because I found a duplicate and voting to close this down.
Actually what I am receiving is a stream of bytes represented as hex, and all the answers indicated do not work. Only [NSData description] gave me true data, which is something I can't use because it is intended for debugging.
Finally I tried the solution given here, and I get what I want.
Thanks to all for trying to help out.
NSString *image1Data = [[NSData dataWithData:myData] encodeBase64ForData];
But for this, you have to use NSData+Base64Additions class.
Use following way
NSString *dC_Str = [[NSString alloc] initWithData:decryPtd_data encoding:NSASCIIStringEncoding] ;

SBJSON parser low memory warning

I am working on JSON data parsing with lots of images downloading and data parsing.I have following code for parsing
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString *responseString = [[NSString alloc] initWithData:webdata encoding:NSASCIIStringEncoding];
[webdata release];
[connection release];
NSDictionary *values = [(NSDictionary*)[responseString JSONValue] objectForKey:#"UserId"];
NSDictionary *Active = [(NSDictionary*)[responseString JSONValue] objectForKey:#"Active"];
[responseString release];
NSString *UserID=[NSString stringWithFormat:#"%#",values];
NSString *Status=[NSString stringWithFormat:#"%#",Active];
[WSDelegate WServiceResponseMsg:#"WS_Authenticate_User" withResponse:UserID forParam:Status];
}
I have many classes with above code for parsing but app crashes after some time interval because of SBJSON parser.In instrument it gives app crashed because of low memory warning.
It is a very wrong assumption that most of the developers have while using SBJSONParser that, it has memory leaks. SBJSONParser does not has any leaks and does not introduces leaks in your code.
It is true that INSTRUMENTS tells you that the leak is because of SBJSONParser, but it denotes something else. Leaks are because of the way you have implemented SBJSONParser APIs. You must have done something wrong in your code.
Go to the leaks in your instruments. Open Extended Details toolbar and see the line of code that has leak. Instruments tells you the nearest place where the leak is.
Better option would be to use NSJSONSerialization that come as a part with iOS 5 and above
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSMutableDictionary *values = [NSJSONSerialization JSONObjectWithData:receivedData options:NSJSONReadingMutableContainers error:&error];
}
Finally got solution.Just use below line for JSON parsing.Remove NSMutableDictionary and use id :
NSError *jsonError = nil;
id allValues = [NSJSONSerialization JSONObjectWithData:webdata
options:0
error:&jsonError];
NSArray *array = [allValues objectForKey:#"Contestants"];

Converting an NSArray of Dictionaries to JSON array in iOS

I need to send an NSArray to the server in the JSON array format. How can I convert it to JSON. This is a sample of my NSArray that I have to pass.
array([0] => array('latitude'=>'10.010490',
'longitude'=>'76.360779',
'altitude'=>'30.833334',
'timestamp'=>'11:17:23',
'speed'=>'0.00',
'distance'=>'0.00');
[1] => array('latitude'=>'10.010688',
'longitude'=>'76.361378',
'altitude'=>'28.546305',
'timestamp'=>'11:19:26',
'speed'=>'1.614',
'distance'=>'198.525711')
)`
and the required format is like this
[
{ "latitude":"10.010490",
"longitude":"76.360779",
"altitude":"30.833334",
"timestamp":"11:17:23",
"speed":"0.00",
"distance":"0.00"
},
{
"latitude":"10.010688",
"longitude":"76.361378",
"altitude":"28.546305",
"timestamp":"11:19:26",
"speed":"1.614",
"distance":"198.525711"
}
]
Any one have solution? Thanks in advance.
NSDictionary *firstJsonDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
#"10.010490", #"latitude",
#"76.360779", #"longitude",
#"30.833334", #"altitude",
#"11:17:23", #"timestamp",
#"0.00", #"speed",
#"0.00", #"distance",
nil];
NSDictionary *secondJsonDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
#"10.010490", #"latitude",
#"76.360779", #"longitude",
#"30.833334", #"altitude",
#"11:17:23", #"timestamp",
#"0.00", #"speed",
#"0.00", #"distance",
nil];
NSMutableArray * arr = [[NSMutableArray alloc] init];
[arr addObject:firstJsonDictionary];
[arr addObject:secondJsonDictionary];
NSData *jsonData2 = [NSJSONSerialization dataWithJSONObject:arr options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData2 encoding:NSUTF8StringEncoding];
NSLog(#"jsonData as string:\n%#", jsonString);
The simplest and best approach !!!
To convert NSArray or NSMutableArray into jsonString you can first convert it into NSData and then further convert that into a NSString. Use this code
NSData* data = [ NSJSONSerialization dataWithJSONObject:yourArray options:NSJSONWritingPrettyPrinted error:nil ];
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
It helped me and hope it helps you as well. All the best.
I would recommend the SBJson-Framework.
Converting an NSMutableArray is as simple as NSString *jsonString = [yourArray JSONRepresentation];
Edit: Jack Farnandish is right u have to transform it into a NSDictionary before you can convert it to Json. In my example the NSMutableArray has to contain the Dictionary. The Array is only needed to create the square brackets at the beginning and the end of the string.
You can use the build in JSON functions of iOS or use an external lib e.g. JSONKit to convert your data to JSON
First You must change you structure into NSDictionary class and NSArray containing NSDictionary objects, then try JSONKit in iOS 5 serialization works better than standard NSJSONSerialization.
#import <JSONKit/JSON.h>
NSArray *array = // Your array here.
NSString *json = [array JSONString];
NSLog(#"%#", json);
JSONKit performs significantly better than SBJson and others in my own and the author's benchmarks.
Check this tutorial, JSON in iOS 5.0 was clearly explained (serailization, deserailization).
Is the service you are calling a RESTful service?
If so, I'd strongly recommend using RestKit. It does object serialization/deserialization. It also handles all the networking underpinnings. Extremely valuable, and well maintained.

Cast JSON object (NSCFDictionary) to string and parse it

I'm working with facebook connect and trying to handle the JSON object that i'm receiving.
I invoked the requstWithGraphPath method and need to get back a JSON object,
tried to parse it and getting an error:
SBJSON *parser = [[SBJSON new] autorelease];
NSData *data = [[NSData alloc] initWithData:result];
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; -> in this line - "[__NSCFDictionary length]: unrecognized selector sent to instance"
NSArray *events = [parser objectWithString:jsonString];
What's the problem?
Can I get the string in an other way or parse the object differently?
Thanks.
If you are working with the delegate callback
- (void)request:(FBRequest *)request didLoad:(id)result;
the parsing work has been done for you. Traverse the NSDictionary or NSArray to find the data you are looking for. If you are working with the delegate callback
- (void)request:(FBRequest *)request didLoadRawResponse:(NSData *)data;
you should initialize an NSString with the data, and use the category method that SBJSON adds to NSString for creating an id. That is assuming the data is data that constructs a string.
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
id result = [jsonString JSONValue];
Are you sure the error happens on that line, or does it happen on the line above?
If result is an NSDictionary (or CFDictionary, same thing), then it is already parsed and you do not need to do that yourself — and it could cause that error message too, on the line above.
The line:
data = [[NSData alloc] initWithData:result];
is almost certainly not what you want to do, as it is equivalent to
data = [result copy];
assuming that result is an NSData object (or NSMutableData), which I'm guessing it isn't.