Ok in simulator but throwing exception in ios device - iphone

when i am running my app in the simulator everything is working perfectly .But when i running the same app in the Ipad exception is being thrown.
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'data parameter is nil.
In my app at one step i have to request a web-URl and need to parsed the returned JSON response. But I have checked the web-url and have been able to parse perfectly in simulator. But all the problem has been arisen in real ios device.But I think i have identified the code where it is getting wrong.
+ (NSDictionary*) getParsedJSON:(NSString*) urlString {
NSLog(#"################################################################################");
NSLog(#"getParsedJSON => urlString:");
NSLog(#"%#", urlString);
NSURL* url = [NSURL URLWithString:urlString];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
NSURLResponse *response1 = nil;
NSError *error = nil;
NSData* response = [NSURLConnection sendSynchronousRequest:request returningResponse:&response1 error:&error];
//NSData* response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSLog(#"--------------------------------------------------------------------------------");
NSString* responseString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSLog(#"getParsedJSON => responseString:\n%#", responseString);
NSLog(#"--------------------------------------------------------------------------------");
NSError* jsonParsingError = nil;
NSDictionary* parsedJSON = [NSJSONSerialization JSONObjectWithData:response options:0 error:&jsonParsingError]; // here is place where exception seems to be thrown.
if (jsonParsingError) {
NSLog(#"ERROR in parsing JSON: %#", jsonParsingError);
} else {
NSLog(#"getParsedJSON => parsedJSON: \n%#", [parsedJSON description]);
}
NSLog(#"################################################################################");
return parsedJSON;
}
I have identified the line where it seems to be wrong .I have also attached screen shot of the exception report..Hoping for your experienced reply.

AS we can see from the logs your response string is null while you are using it on your Device. This may be due to some internet access problem. Try to Use:
if([response isequaltostring:#"(null)"]||response == nil || response.length == 0)
{
NSError* jsonParsingError = nil;
NSDictionary* parsedJSON = [NSJSONSerialization JSONObjectWithData:response options:0 error:&jsonParsingError]; // here is place where exception seems to be thrown.
if (jsonParsingError) {
NSLog(#"ERROR in parsing JSON: %#", jsonParsingError);
}
else {
NSLog(#"getParsedJSON => parsedJSON: \n%#", [parsedJSON description]);
}
}
Also try to add the exceptional breakpoint and post where exactly the app crashed.
Let me know the result.

First, you need to set an exception breakpoint in Xcode - there are many posts here on how to do that. Second, after each of you statements where an object is created or returned, add an assert:
NSURL *foo = ...
assert(foo);
Doing this will help you find the first issue not the last one.

As per your logs, your response string is empty!
Do the below two things!
Add NSLog(#"Response Data: %#",response); and check if the response has value?
If 'response' has value, convert it to a string - Log the string value - And check if the any of the key has nil value?
'NSJSONSerialization JSONObjectWithData' method would crash if it finds any key with nil value.

Related

iOS app crashing if data is inaccessible

I'm using the following to request data using NSJSONSerialization. The problem I'm having is that if the data is inaccessible (e.g. no network connection) the app crashes. How could I go about stopping the app from crashing if the network or server is down?
I'm calling [self requestData]; in the viewDidLoad: method
-(void)requestData {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL
URLWithString:#"http://example.com/api/nodes"]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSError *jsonParsingError = nil;
NSDictionary *publicData = [NSJSONSerialization JSONObjectWithData:response
options:0
error:&jsonParsingError];
publicDataArray = [publicData objectForKey:#"data"];
for(publicDataDict in publicDataArray) {
NSLog(#"data output is %#",[publicDataDict objectForKey:#"title"]);
}
}
thanks for any help
Some thoughts:
Use Reachability for checking network connection
Always use asynchronous request, else it'll block your UI till the app get the response from server.
Always use exception handling
Here the issue is:
You are calling a synchronous request in the viewDidLoad using sendSynchronousRequest. But the server is down, so you won't get the result, and it still expect any data to come. But your app won't load untill that request finishes. Due to this springboards application-watchdog will terminate your app.
What is Watch dog ?
watchdog — In order to keep the user interface responsive, iOS
includes a watchdog mechanism. If your application fails to respond to
certain user interface events (launch, suspend, resume, terminate) in
time, the watchdog will kill your application and generate a watchdog
timeout crash report. The amount of time the watchdog gives you is not
formally documented, but it's always less than a network timeout.
Please check this Technical question on Apple site.
Why don't you check if [NSURLConnection sendSynchronousRequest:] got any error?
NSError *requestError = nil;
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
if (requestError)
{
NSLog(#"sync. request failed with error: %#", requestError);
}
else
{
// handle data
}
And you really should check if NSJSONSerialization had an error too:
NSError *jsonParsingError = nil;
NSDictionary *publicData = [NSJSONSerialization JSONObjectWithData:response
options:0
error:&jsonParsingError];
if (jsonParsingError)
{
NSLog(#"JSON parsing failed with error: %#", jsonParsingError);
}
else
{
// do something
}

AFJSONRequestOperation crashing with "data parameter is nil" NSJSONSerialization error

I previously asked a similar question on this but didn't get much help and have now looked into it further and still can't see why I have a problem.
NSURL *url = [NSURL URLWithString:#"http://datapoint.metoffice.gov.uk/public/data/val/wxfcs/all/json/sitelist?res=daily&key=<MY API KEY>"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"Success");
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Fail");
}];
[operation start];
This fails with the following
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'data parameter is nil'
I believe the problem is due to the JSON type returned as ISO-8859-1, I managed to get this working with NSJSONSerialization by encoding the retuned string to NSUTF8StringEncoding
Example...
NSString *string = [NSString stringWithContentsOfURL:kMetOfficeAllSites encoding:NSISOLatin1StringEncoding error:&error];
NSData *metOfficeData = [string dataUsingEncoding:NSUTF8StringEncoding];
id jsonObject = [NSJSONSerialization JSONObjectWithData:metOfficeData options:kNilOptions error:&error];
if (error) {
//Error handling
} else {
//use JSON
So I looked at responseJSON in AFJSONRequestOperation.m
- (id)responseJSON {
[self.lock lock];
if (!_responseJSON && [self.responseData length] > 0 && [self isFinished] && !self.JSONError) {
NSError *error = nil;
// Workaround for behavior of Rails to return a single space for `head :ok` (a workaround for a bug in Safari), which is not interpreted as valid input by NSJSONSerialization.
// See https://github.com/rails/rails/issues/1742
if ([self.responseData length] == 0 || [self.responseString isEqualToString:#" "]) {
self.responseJSON = nil;
} else {
// Workaround for a bug in NSJSONSerialization when Unicode character escape codes are used instead of the actual character
// See http://stackoverflow.com/a/12843465/157142
NSData *JSONData = [self.responseString dataUsingEncoding:self.responseStringEncoding];
self.responseJSON = [NSJSONSerialization JSONObjectWithData:JSONData options:self.JSONReadingOptions error:&error];
}
self.JSONError = error;
}
[self.lock unlock];
return _responseJSON;
}
The code is crashing in the else statement, however this seems to be doing what I was doing previously when using NSJSONSerialization directly and re-encoding the responseString.
I even hardcoded dataUsingEncoding to NSUTF8StringEncoding but it still crashes and I don't understand why?
Note: The above works fine with other JSON feeds, also from other feeds on
http://datapoint.metoffice.gov.uk/ but
http://datapoint.metoffice.gov.uk/public/data/val/wxfcs/all/json/sitelist?res=daily&key=
includes the place name Sóil Chaorainn which causes the problem
The problem seems to be that the text encoding of the response is wrong. There are characters that can't be encoded using ISO-8859-1. This is why the responseString method (see AFURLConnectionOperation.m) returns nil and the JSON serialization fails.
To solve the issue you could subclass AFJSONRequestOperation and override responseStringEncoding in this way to enforce UTF-8 encoding:
- (NSStringEncoding)responseStringEncoding {
[self.lock lock];
if (!_responseStringEncoding && self.response) {
self.responseStringEncoding = NSUTF8StringEncoding;
}
[self.lock unlock];
return _responseStringEncoding;
}

NSdictionary is not Null, but showing 0 key/value

I am fetching data from server using json. It is checked url is getting hit response is received, printed in console all values fetched from json. But dictionary and tried with array also both are showing null values by breakpoints but when printed in console showing data is fetched. Below is the code.
NSString *urlStr = [NSString stringWithFormat:#"http://server39.pivbfg.com/360ads/apps/ads/%#/android/1360/ord0.9109502528132325?json=1&package_url=%#",self.mStrPid, base64String];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:
[NSURL URLWithString:
[urlStr stringByAddingPercentEscapesUsingEncoding:
NSUTF8StringEncoding]]];
NSLog(#"req-------------%#",request);
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSDictionary *json_dict = [json_string JSONValue];
NSLog(#"json_dict\n%#",json_dict);
NSLog(#"json_string\n%#",json_string);
NSMutableArray *arrAds = [[NSMutableArray alloc]init];
arrAds = [json_dict valueForKey:#"ads"];
request is going ok.
json_string is ok.
But json_dict printing values in console but showing null at breakpoints. What could be the reason for this. One thing is i am using ARC, does it affect this code. Please guide for the above.
This is the error: * Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFString 0x9851e00> valueForUndefinedKey:]: this class is not key value coding-compliant for the key ads.'* First throw call stack:
(0xb5012 0x13a9e7e 0x13dfb1 0xe565ed 0xdc28db 0xdc288d 0x613d 0x3d1707 0x3d1772 0x320915 0x320caf 0x320e45 0x329e57 0x5942 0x2ed697 0x2edc87 0x2eee8b 0x3001f5 0x30112b 0x2f2bd8 0x2202df9 0x2202ad0 0x2abf5 0x2a962 0x5bbb6 0x5af44 0x5ae1b 0x2ee6ba 0x2f053c 0x544d 0x2b65 0x1)
libc++abi.dylib: terminate called throwing an exception
Edited code
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSError *error;
NSData *jsonData = [json_string dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *results = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
NSLog(#"results\n%#",results);
NSMutableArray *arrAds = [[NSMutableArray alloc]init];
arrAds = [results valueForKey:#"ads"];
NSLog(#"dict-------------%#",arrAds);
Now the same problem is coming with the array arrAds. It is printing values in console but empty.
Well the error tells you that the property you are retrieving from the JSON is not a dictionary but a string. It looks like you json_string does not contain a valid JSON object.
In your example you'r also leaking:
NSMutableArray *arrAds = [[NSMutableArray alloc]init];
arrAds = [json_dict valueForKey:#"ads"];
You create a new NSMutableArray only to assing a new object to the same variable the next line. Also the object returned will not a none mutable version. You can just replace it with:
NSMutableArray *arrAds = [[json_dict objectForKey:#"ads"] mutableCopy];

JSON returning null

I'm having a bit of trouble parsing some returned JSON. I'm fairly new to working with JSON. I'm trying to get the company name from the first JSON array element. I have a feeling that I'm confusing the use of NSMutabeArray and NSMutableDictionary. What I get is null. Any idea what I'm doing wrong?
NSString *url = #"http://www.google.com/finance/info?infotype=infoquoteall&q=C,JPM,AIG,AAPL";
NSData* data = [NSData dataWithContentsOfURL:
[NSURL URLWithString: url]];
//parse out the json data
NSError* error;
NSMutableArray* json = [NSJSONSerialization
JSONObjectWithData:data //1
options:kNilOptions
error:&error];
NSString* companyName = [[json objectAtIndex:0] objectForKey:#"name"] ; //Where I need some help
NSLog(#"we got %#", companyName);
Load that url in your browser. Looks like google is prefixing the JSON with //. I think NSJSONSerialization is tripping on that. Try this
NSRange range = NSMakeRange(2, [data length] - 3);
NSData *noPrefix = [data subdataWithRange:range];
Then send that to the parser.
You put in an error object, but you never looked at it. If you had, you would see that the data is corrupted:
Error Domain = NSCocoaErrorDomain Code = 3840 "The data couldn’t be read because it has been corrupted." (Invalid value around character 1.) UserInfo = 0x10030a8f0 { NSDebugDescription = Invalid value around character 1. }
I changed the value of the options parameter to see this error. I have
NSMutableArray* json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers |NSJSONReadingAllowFragments error:&error];

iPhone SDK Remote file exists, without cache

I need to check if a file exists on my server without using cache. The methods I have used are all returning a 200, even if the file does not exist, so I can only assume there is a cache problem, or theres a problem with my code.
Heres my code: for arguments sake..the URL is changed in this example, but the url is correct in my code.
NSString *auth = [NSString stringWithFormat:#"http://www.mywebsite.com/%#.txt",[self aString]];
NSURL *authURL = [NSURL URLWithString:auth];
NSURLRequest* request = [NSURLRequest requestWithURL:authURL
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:5.0];
NSURLConnection *conn = [NSURLConnection connectionWithRequest:request
delegate:self];
NSHTTPURLResponse* response = nil;
NSError* error = nil;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"statusCode = %d", [response statusCode]);
if ([response statusCode] == 404)
NSLog(#"MISSING");
else
NSLog(#"EXISTS");
the response is always 200, even if I rename the file on the server.
There are a couple of potential problems with your code. First, when you create conn using connectionWithRequest:delegate: you are starting an asynchronous request. The response would be received in the delegate's (self in your case) connection:didReceiveResponse: method. Are you trying to do the request asynchronously? From the rest of your code though, it looks like you are actually trying to do a synchronous request. That's what sendSynchronousRequest:returningResponse:error: is for. If that's what you intend, then you don't need the earlier call to create a connection.
Assuming thats the case, you need to capture and check the value returned from calling sendSynchronousRequest:returningResponse:error:. It will return nil if the connection failed, which is what I suspect is happening. You can then look at the error returned to figure out what is going on. Try something like:
NSData * result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (result != nil) {
NSLog(#"statusCode = %d", [response statusCode]);
if ([response statusCode] == 404)
NSLog(#"MISSING");
else
NSLog(#"EXISTS");
} else {
NSLog(#"%#", error);
}
Is it possible it's caching on the server side? If so you could try NSURLRequestReloadIgnoringLocalAndRemoteCacheData instead of NSURLRequestReloadIgnoringCacheData.