I am calling Google's geocoding API and the Distance Matrix API on an asynchronous thread in my app.But its giving out an NSRangeException.
Here's my code:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^
{
NSString *urlStringGeoCoding;
NSString *urlString;
urlStringGeoCoding = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/"
#"api/geocode/json?"
#"latlng=40.714224,-73.961452&sensor=true"];
urlString = [NSString stringWithFormat:#"http://maps.googleapis.com"
#"/maps/api/distancematrix/json?"
#"origins=%#&destinations=%#&mode=driving&"
#"language=en&sensor=true&units=imperial","
#"current,#"Chicago,IL"];
NSURL *urlGeo = [NSURL URLWithString:[urlStringGeoCoding
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURL *url = [NSURL URLWithString:[urlString
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSData *googledatageo = [NSData dataWithContentsOfURL:urlGeo];
NSData *googledata = [NSData dataWithContentsOfURL:url];
NSError *errorgeo;
NSError *error;
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:googledata
options:kNilOptions
error:&error];
NSMutableDictionary *jsongeo = [NSJSONSerialization JSONObjectWithData:googledatageo
options:kNilOptions
error:&errorgeo];
NSString *result = [[[[[[json objectForKey:#"rows"] objectAtIndex: 0] objectForKey:#"elements"] objectAtIndex:0]objectForKey:#"distance"]objectForKey:#"text"];
if(jsongeo)
{
NSString *resultgeo = [[[jsongeo objectForKey:#"results"] objectAtIndex: 0] objectForKey:#"formatted_address"] ;
}
dispatch_sync(dispatch_get_main_queue(), ^
{
cell.distanceLabel.text = result;
});
});
Here's the error I am getting:
Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayI objectAtIndex:]: index 0 beyond bounds for empty array'
* First throw call stack:
(0x289a012 0x2210e7e 0x284fb44 0x1318c 0x57f953f 0x580b014 0x57fc2e8 0x57fc450 0x9112ae72 0x91112d2a)
How do I prevent the Range Exception here?
You prevent these range exceptions by checking the count of the "rows", "elements", and "results" arrays, before calling objectAtIndex: on them.
It was a good idea to break up these two very long lines that assign result and resultgeo anyway; just use a few temporary NSArray variables.
Related
In the below code I am trying to check if my Documents Directory Url is empty, so in case it's empty it will show now way or continue to do what ever I need.
Here is my code:
- (IBAction)saveVideo:(id)sender {
NSURL *vedioURL;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *filePathsArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:documentsDirectory error:nil];
NSLog(#"files array %#", filePathsArray);
NSString *fullpath;
for ( NSString *apath in filePathsArray )
{
fullpath = [documentsDirectory stringByAppendingPathComponent:apath];
vedioURL =[NSURL fileURLWithPath:fullpath];
}
NSLog(#"vurl %#",vedioURL);
NSURL *movieUrl = [NSURL fileURLWithPath:fullpath];
NSString *moviePath = [movieUrl path];
if (videoUrl.absoluteString.length == 0) {
NSLog(#"No way");
} else {
self.imageViewPost.image = [self generateThumbImage:moviePath];
AVPlayerItem * playeritem = [AVPlayerItem playerItemWithURL:vedioURL];
[_player replaceCurrentItemWithPlayerItem:playeritem];
[_player play];
[self clearTmpDirectory];
}
}
The app crashed and it shows Null value to my Url:
vurl (null)
2017-11-29 20:54:24.288473+0400 EasyVideo[43587:2429960] ***
Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '*** -[NSURL initFileURLWithPath:]: nil string parameter'
I hope to solve this issue.
Thanks
You can first get the data from the URL and check if it is not empty.
NSData *data = [NSData dataWithContentsOfURL:videoURL];
Here,if data is not empty you will perform the task accordingly:
if (data == nil)
{
//Do not perform the task.
}
else
{
//perform the task
}
I'm trying to parse a JSON file so I can use it's contents as NSStrings and display in UILabels throughout my application.
My JSON:
{
"CustomText": [
{
"bodyText": "This is the body text",
"loginText": "This is the loginText",
"extraText": "This is the extra text"
}
]
}
My code:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"File" ofType:#"json"];
NSData *content = [[NSData alloc] initWithContentsOfFile:filePath];
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:content options:kNilOptions error:nil];
NSArray *customStrings = json[#"CustomText"];
NSString *body = [customStrings valueForKey:#"bodyText"];
NSString *login = [customStrings valueForKey:#"loginText"];
self.labelText.text = body;
I'm not sure why it breaks, I have looks and surprisingly didn't find much on how to best use a local JSON file. Any help would be great.
Error message:
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[__NSArrayI length]:
unrecognized selector sent to instance 0x7f8080781740'
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"File" ofType:#"json"];
NSData *content = [[NSData alloc] initWithContentsOfFile:filePath];
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:content options:kNilOptions error:nil];
NSArray *customStrings = json[#"CustomText"];
NSString *body = [[customStrings objectAtIndex:0] valueForKey:#"bodyText"];
NSString *login = [[customStrings objectAtIndex:0] valueForKey:#"loginText"];
self.labelText.text = body;
Use keypath
NSString * body = [json valueForKeyPath:#"CustomText.bodyText"];
self.labelText.text = body;
So I have the photograph below which is a screenshot I took of a JSON script I am trying to read from a URL. In the code section below, I managed to get the 'name' attribute and assign it to the 'name' NSString object, but when I try do the same for 'address' I get the following error:
[__NSCFDictionary objectAtIndexedSubscript:]: unrecognized selector sent to instance 0x174260980
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary objectAtIndexedSubscript:]: unrecognized selector sent to instance 0x174260980'
whats the difference between how I did it inside 'venues' than inside 'location'? I tried many different ways to do it, some including arrays, but nothing seems to work.
NSURL *url = [NSURL URLWithString:urlString];
NSData *jsonData = [NSData dataWithContentsOfURL:url];
NSError *error = nil;
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
NSDictionary *responseDictionary = [dataDictionary objectForKey:#"response"];
NSDictionary *venueDictionary = [responseDictionary objectForKey:#"venues"];
for (NSDictionary *dict in venueDictionary) {
NSLog(#"%#", dict);
NSString *name = [dict objectForKey:#"name"];
NSDictionary *locationDictionary = [dict objectForKey:#"location"];
for (NSDictionary *locationDict in locationDictionary) {
NSString *address = [locationDict objectForKey:#"address"];
NSLog(#"%#", address);
}
}
You're expecting the "location" key to point to an array, but it doesn't. It points to an object, get rid of for (NSDictionary *locationDict in locationDictionary) { and just pull the address out of locationDictionary instead.
I tried to parse this:
{"event":[{"event_id":"9","title":"event 10","welcome_logo":"20140715130727_252.png"}],"succeed":1}
This is my code:
NSString *strURL=[NSString stringWithFormat:#"http://loc**host/summit/event_login.php"];
NSData *dataURL=[NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];
NSString *strResult=[[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding];
NSArray *jsonArray=[NSJSONSerialization JSONObjectWithData:dataURL options:0 error:nil];
NSDictionary *element=[jsonArray objectAtIndex:0];
NSString *title = [element objectForKey:#"title"];
NSString *image = [element objectForKey:#"welcome_logo"];
But this guy came and disturbs me:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0x9e7d010'
So I'm wondering what I did I do wrong. I tried to google it and many said that I assume to use an array when the data is actually a dictionary. Is that true? So what do I need to do?
Change
NSArray *jsonArray=[NSJSONSerialization JSONObjectWithData:dataURL options:0 error:nil];
NSDictionary *element=[jsonArray objectAtIndex:0];
to
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:dataURL options:0 error:nil];
NSArray *events = [jsonDict objectForKey:#"event"];
if ([events count] > 0) {
NSDictionary *element=[events objectAtIndex:0];
}
because your json data is in the form of dictionary. And event holds the list (array) of events. And do a count check before accessing objectAtIndex: from events.
I am only starting with IOS Development and creating an IOS application (Final project) for my computer science class which uses JSON to get data from remote MySql database.
Here is the method I call from ViewDidLoad:
- (void)loadJSON
{
//-- Make URL request with server
NSHTTPURLResponse *response = nil;
NSString *jsonUrlString = [NSString stringWithFormat:#"http://vito-service.ru/studentsconnect/profile.php"];
NSURL *url = [NSURL URLWithString:[jsonUrlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
//-- Get request and response though URL
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url];
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
//-- JSON Parsing
NSMutableArray *result = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:nil];
NSLog(#"Result = %#",result);
}
and NSLog prints the correct data:
Result = {
users = (
{
IdUser = 1;
facebook = "";
fullname = "";
instagram = "";
phonenumber = "";
username = moderas;
},
{
IdUser = 2;
facebook = "fb.com/petroffmichael";
fullname = "Michael Perov";
instagram = "#petroffmichael";
phonenumber = "(650)557-6168";
username = petroffmichael;
},
{
IdUser = 3;
facebook = "fb.com/testuser";
fullname = "Test User";
instagram = "#testuser";
phonenumber = "111 111-1111";
username = testuser;
}
);
}
But how can I retrieve this data as Strings to put them to the labels then? I tried lots of different options of creating Data objects, which I found here on stack overflow but I always get an "unrecognized selector sent to instance" error. I also tried creating a separate NSObject
#synthesize IdUser, username, fullname, phonenumber, facebook, instagram;
- (id) initWithUsername: (NSString *)uUsername andUserFullName: (NSString *)uFullname andUserPhonenumber: (NSString *)uPhonenumber andUserFacebook: (NSString *)uFacebook andUserInstagram: (NSString *)uInstagram andUserId: (NSString *)uId
{
self = [super init];
if (self) {
username = uUsername;
fullname = uFullname;
phonenumber = uPhonenumber;
facebook = uFacebook;
instagram = uInstagram;
IdUser = uId;
}
return self;
}
and then retrieving data with this method:
-(void)retrieveData
{
NSURL *url = [NSURL URLWithString:getDataUrl];
NSData *data = [NSData dataWithContentsOfURL:url];
jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
usersArray = [[NSMutableArray alloc] init];
for (int i=0; i<jsonArray.count; i++) {
NSString * uId = [[jsonArray objectAtIndex: i] objectForKey:#"IdUser"];
NSString * uUsername = [[jsonArray objectAtIndex: i] objectForKey:#"username"];
NSString * uFullname = [[jsonArray objectAtIndex: i] objectForKey:#"fullname"];
NSString * uPhonenumber = [[jsonArray objectAtIndex: i] objectForKey:#"phonenumber"];
NSString * uFacebook = [[jsonArray objectAtIndex: i] objectForKey:#"facebook"];
NSString * uInstagram = [[jsonArray objectAtIndex: i] objectForKey:#"instagram"];
[usersArray addObject:[[User alloc] initWithUsername:uUsername andUserFullName:uFullname andUserPhonenumber:uPhonenumber andUserFacebook:uFacebook andUserInstagram:uInstagram andUserId:uId]];
}
}
I have all the important #import's but I still get the same error:
2014-04-23 18:35:26.612 testimage[47155:70b] -[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0xa72a8b0
2014-04-23 18:35:26.813 testimage[47155:70b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0xa72a8b0'
Can anybody please help to find the right solution?
Thanks!
After listening to multiple comments I changed the code but still receive an error..
I guess I am still doing something wrong
jsonArray is not an array anymore:
#property (nonatomic, strong) NSDictionary *jsonArray;
#property (nonatomic, strong) NSMutableArray *usersArray;
Then the method:
-(void)retrieveData
{
NSURL *url = [NSURL URLWithString:getDataUrl];
NSData *data = [NSData dataWithContentsOfURL:url];
jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
usersArray = [[NSMutableArray alloc] init];
for (NSDictionary *dict in jsonArray)
{
NSString * uId = [dict objectForKey:#"IdUser"];
NSString * uUsername = [dict objectForKey:#"username"];
NSString * uFullname = [dict objectForKey:#"fullname"];
NSString * uPhonenumber = [dict objectForKey:#"phonenumber"];
NSString * uFacebook = [dict objectForKey:#"facebook"];
NSString * uInstagram = [dict objectForKey:#"instagram"];
[usersArray addObject:[[User alloc] initWithUsername:uUsername andUserFullName:uFullname andUserPhonenumber:uPhonenumber andUserFacebook:uFacebook andUserInstagram:uInstagram andUserId:uId]];
}
}
And I am still getting the same error:
2014-04-23 20:44:43.971 testimage[48285:70b] -[__NSCFString objectForKey:]: unrecognized selector sent to instance 0xa5547d0
2014-04-23 20:44:44.053 testimage[48285:70b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0xa5547d0'
Look closely at that output. It isn't what you say. What you have there is not an array — it's a dictionary with one key, #"users", whose value is an array. That's what it's telling you when it starts with { users = …. If you want the array, you'll need to retrieve it from the dictionary.
Try this:
NSDictionary *res = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:nil];
NSMutableArray *result = [res objectForKey:#"users"];
This will do. The response isn't a NSArray. It is a Dictionary. First get the array from the dictionary and then use it as you are using. Hope this helps... :)
EDIT:
You can rewrite the loop by this:
for (NSDictionary *dict in jsonArray)
{
//dict is a NSDictionary. Just get value for keys
}