Can reusing the same NSError object be problematic? - ios

I have since changed my implementation to not do this anymore, but I would be interested in knowing if the following could lead to issues - take for example a process that has multiple steps, each involving passing a reference to an NSError object. If you were to reuse this error object each step along the way, would that reference be negatively effected in some way, perhaps leading to some sort of memory management/dealloc crash?
Example (most of the in-between code has been omitted)
NSError *error;
NSData *data = [NSJSONSerialization dataWithJSONObject:object options:0 error:&error];
if (!data) {
return error;
}
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (!responseData) {
return error;
}
NSDictionary *resultDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
if (!resultDictionary) {
return error;
}
Even though the error is never "used" twice, meaning the error will be nil (it seems) the next time its reference is passed to another method, could the reference be effected in some way at any of the steps along the way?
Original code prior to editing in response to jlehr's comments:
NSError *error;
NSData *data = [NSJSONSerialization dataWithJSONObject:object options:0 error:&error];
if (error) {
return;
}
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (error) {
return;
}
NSDictionary *resultDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
if (error) {
return;
}
EDIT: To anyone coming to this at a later date, the information jlehr is referring to can be found here:
When dealing with errors passed by reference, it’s important to test
the return value of the method to see whether an error occurred, as
shown above. Don’t just test to see whether the error pointer was set
to point to an error.
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/ErrorHandling/ErrorHandling.html

According to Apple's documentation, you should never check an NSError object returned by reference. Instead, check the return value of the init... method or factory method you're calling, for example:
NSError *error;
NSData *data = [NSJSONSerialization dataWithJSONObject:object options:0 error:&error];
if (data == nil) {
// Handle failure. It's safe to use the error object here.
}
However, your code doesn't appear to be doing anything with the NSError instance, (e.g., logging, or displaying an alert), so you can just pass NULL instead.
NSData *data = [NSJSONSerialization dataWithJSONObject:object options:0 error:NULL];
if (data == nil) {
// Handle failure.
}

Related

Appending data from several url JSON calls - into one NSDictionary

So, i have a loop where i repeatedly call an url, which returns contacts in JSON format.
Since i call the url more than once, i want to add it all up, an ultimately end up with a NSDictionary, containing contacts for all the url calls.
What i'm doing now, is appending the data for each iteration:
NSData *response = [NSURLConnection sendSynchronousRequest:request
returningResponse:nil error:nil];
[data appendData:response];
and when the loop is over i try to make it into a NSDictionary:
// Loop over - create Dict from all the data.
NSDictionary *JSONDataFinal = [NSJSONSerialization JSONObjectWithData:data
options:0 error:&error2];
I get an error: "garbage at end" and believe the approach is wrong, since it doesn't know how to put data from each consecutive call into the same key, and not create a key for each call.
Should i create a Dictionary for each iteration - and combine them in the end?
You can append data to a NSMutableDictionary after each call.
NSMutableDictionary* jsonDict = [[NSMutableDictionary alloc] init];
for (...) {
...
NSData *response = [NSURLConnection sendSynchronousRequest:request
returningResponse:nil error:nil];
NSDictionary *JSONData = [NSJSONSerialization JSONObjectWithData:data
options:0 error:&error2];
[jsonDict addEntriesFromDictionary:JSONData];
}
Create different dictionary for each json data and store in main array like this:
NSMutableArray *arrAllContacts = [NSMutableArray array];
//here arrJsonURL which stores all url for contacts
for(int i=0; i<[arrJsonURL count]; i++)
{
//create request
...............
NSData *response = [NSURLConnection sendSynchronousRequest:request
returningResponse:nil error:nil];
[data appendData:response];
NSError *error = nil;
//get dictionary from json data
NSDictionary *dictContact = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
[arrAllContacts addObject:dictContact];
}

NSJSONSerialization json object leads to annoying empty XCode debug variables

I'm using NSJSONSerialization's JSONObjectWithData method to serialize json response data into a NSDictionary hierarchy, as part of my API handling in IOS. This works great. The long standing tedious part however is that when using the XCode debugger, the nested json data structure is not viewable in the variable watcher. This can best be seen in the photo at the end. The data is all accessible and navigable in the code, it just isn't for the debugger.
Is there any way to clean this up or serialize it better?
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
if (error){
NSLog(#"Request Error: %#", [error localizedDescription]);
if(completionHandler != nil){
completionHandler(nil,error);
}
} else {
NSError *jsonerror = nil;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonerror];
if(jsonerror) {
NSLog(#"JSON Serialize Error: %#", [jsonerror localizedDescription]);
if(completionHandler != nil){
completionHandler(nil,jsonerror);
}
} else {
if(completionHandler != nil){
completionHandler(json,nil); // usual successful json route
}
}
}
}];
Try using AFNeteorking for serialization.
https://github.com/AFNetworking/AFNetworking
It might help.
If not you can print what ever you need in the console part of the debugger using po.
po object
For example

How can I parse this JSON information?

Here is what I want to parse.
{
"Words": {
"subjugate": "To conquer. ",
"contemplate": "To consider thoughtfully. ",
"comprise": "To consist of. ",
"pollute": "To contaminate. "
}
}
Here is a very stripped and over-simplified way to handle getting response data back from a server in JSON and serializing the JSON to an NSDictionary:
// this is just for example purposes, in this example the code is already running on a background thread so sending it synhcronously is OK, and I've already created the request object
NSError *error = nil;
NSHTTPURLResponse *response = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
// if we don't have response data
if (!responseData) {
// handle that we got no response from the server
}
if (error) {
// handle the request error
}
// serialize the JSON result into a dictionary
NSError *serializationError = nil;
NSDictionary *resultDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:0 &serializationError];
if (serializationError) {
// handle the error turning the data into dictionary
}
NSDictionary *wordsDictionary = resultDictionary[#"words"];
NSString *exampleValue = wordsDictionary[#"subjugate"]; // will be "To conquer." if everything goes to plan
You can parse as bellow
NSData *data = [#"{\"Words\":{\"subjugate\":\"To conquer.\",\"contemplate\":\"To consider thoughtfully.\",\"comprise\":\"To consist of.\",\"pollute\":\"To contaminate.\"}}" dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
if(error)
{
NSLog(#"Error : %#", error);
}
else
{
NSLog(#"%#", json);
}

Null form JSON file when using dataWithContentsOfURL

I'm trying to connect to a JSON file on my server (witch is a valid JSON file), but it returns NULL(jsonData is NULL not the json). The code works whit other url's but not with mine, and when loaded in a web browser every thing is fine.
Here is the code i'm using.
NSData *jsonData = [NSData dataWithContentsOfURL:url];
NSError *error = nil;
id json = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error];
Use the following method to get the possible error in loading the data with your url:
NSError *error = nil;
NSData *jsonData = [NSData dataWithContentsOfURL:url
options:NSDataReadingUncached
error:&error];
if (error) {
NSLog(#"error: %#", error);
} else {
// ... do stuff
}
A common error to occur in a development environment is when the server you are calling is on a local network and you are trying to access from a device on an external network. Make sure this is not the case.
I think the problem is you are passing url as string. Passed it as a url. Use this for converting into data:-
NSData *jsonData =[NSData dataWithContentsOfURL:[NSURL URLWithString:yoururlString]];

Cannot parsing Json to NSDictionary

I have a WebService, which give me the fallowing Json-String back:
"{\"password\" : \"1234\", \"user\" : \"andreas\"}"
I call the webservice and try to parse the returned data like:
[NSURLConnection sendAsynchronousRequest: request
queue: queue
completionHandler: ^(NSURLResponse *response, NSData *data, NSError *error) {
if (error || !data) {
// Handle the error
} else {
// Handle the success
NSError *errorJson = nil;
NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableContainers error: &errorJson];
NSString *usr = [responseDict objectForKey:#"user"];
}
}
];
But the resulting NSDictionary looks like:
What has the effect, that I cannot get the values - for example user.
Can someone help me, what I am doing wrong? - Thank you.
From the debugger screenshot is seems that the server is (for whatever reason) returning
"nested JSON": responseDict[#"d"] is a string containing JSON data again, so you have to
apply NSJSONSerialization twice:
NSError *errorJson = nil;
NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData: data options:0 error: &errorJson];
NSData *innerJson = [responseDict[#"d"] dataUsingEncoding:NSUTF8StringEncoding];
NSMutableDictionary *innerObject = [NSJSONSerialization JSONObjectWithData:innerJson options:NSJSONReadingMutableContainers error:&errorJson];
NSString *usr = [innerObject objectForKey:#"user"];
If you have the option, a better solution would be to fix the web service to return
proper JSON data.

Resources