Adding bounds to google maps search string causes nil results - ios

I added a search box to my mapping app a little while back which was doing very simple address searching with minimal options.
http://maps.googleapis.com/maps/api/geocode/json?address=sydney+grove&sensor=true
I've just added bounds parameters using the current screen viewport like this
http://maps.googleapis.com/maps/api/geocode/json?address=sydney+grove&bounds=51.198083,-0.830125|51.799930,0.576125&sensor=true
it returns a result when pasted into a browser but always a nil result if entered in code (jsonResponse always equals nil)
-(void) doGeocodingBasedOnStringUsingGoogle:(NSString*) searchString {
GMSCoordinateBounds* bounds=[[self datasource] searchBounds];
//CREATE LOOKUP STRING
NSString *lookUpString = [NSString
stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?
address=%#&bounds=%f,%f|%f,%f&sensor=true",
searchString,
bounds.southWest.latitude,
bounds.southWest.longitude,
bounds.northEast.latitude,
bounds.northEast.longitude];
lookUpString = [lookUpString stringByReplacingOccurrencesOfString:#" "
withString:#"+"];
//SEARCH FOR RESULTS
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSError *error = nil;
NSData *jsonResponse = [NSData dataWithContentsOfURL:[NSURL URLWithString:lookUpString]];
if (jsonResponse) {
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonResponse options:kNilOptions error:&error];
self.searchResults = [jsonDict valueForKey:#"results"];
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableview reloadData];
});
});
}
This code was fine before I added the bounds condition and is fine if I remove so I'm really out of ideas

I think you need to replace the | with a %7C, for example see here:
How to make an NSURL that contains a | (pipe character)?
As mentioned in the comments on the answer, you could look into using stringByAddingPercentEscapesUsingEncoding for a method to escape the URL for you (so eg you wouldn't need to replace spaces with a +, etc).

Related

Corruption of NSString or encoding issue in Objective C

Please see code below:
+ (void)splashDataFromJSON:(NSData *)objectNotation error:(NSError **)error
{
NSError *localError = nil;
NSDictionary *parsedObject = [NSJSONSerialization JSONObjectWithData:objectNotation options:0 error:&localError];
if (localError != nil) {
*error = localError;
}
NSMutableArray* btms = [[NSMutableArray alloc] init];
NSMutableDictionary* btmManufacturerResolutionDictionary = [[BTMCache sharedManager] btmManufacturerResolutionDictionary];
NSArray *results = [parsedObject valueForKey:#"results"];
NSLog(#"Count %d", parsedObject.count);
NSString* imageBaseUrl = [[parsedObject valueForKey:#"general"] valueForKey:#"image_base_url"];
imageBaseUrl = [imageBaseUrl stringByAppendingString:#"hdpi/"];
NSString* splashImageName = [[[parsedObject valueForKey:#"general"] valueForKey:#"splash"] valueForKey:#"img"];
NSString* splashAdvertiserURL = [[[[parsedObject valueForKey:#"general"] valueForKey:#"splash"] valueForKey:#"url"] copy];
NSMutableString* appendedString = [[NSMutableString alloc] init];
for(int i =0 ;i<[splashAdvertiserURL length]; i++) {
char character = [splashAdvertiserURL characterAtIndex:i];
printf(&character);
sleep(0.1);
if (character != "!")
{
[appendedString appendFormat:#"%c", character];
}
}
[[SplashData sharedManager] setSplashAdvertiserURL:appendedString];
[[SplashData sharedManager] setSplashImageName:splashImageName];
splashAdvertiserURL = [[SplashData sharedManager] splashAdvertiserURL];
}
The point of interest is in splashAdvertiserURL. When I receive this data and print it out using po, it comes out as "https://radar.com/ref/go/84/". This is fine and what was expected. When I look at the incoming data in JSONLint it looks like this:
"general": {
"image_base_url": "https:\/\/radar.com\/img\/manufacturers\/",
"splash": {
"img": "image1.png",
"url": "https:\/\/radar.com\/ref\/go\/84\/"
}
},
As you can see, further on I put the NSString into a singleton with an NSString property. Nothing abnormal here. I then proceed to retrieve it to see that all is ok. Further to this the program continues. In another class I wish to retrieve this information, and when I try and do that, it throws EXC_BAD_ACCESS. There appears to be garbage in there.
I then put in a loop in the code as you can see to print out the characters one at a time. Very curiously, when I print that out using po I get:
https://
r
a
d
ar.com/ref/go/8 4!/"
Exactly in that format. If I then proceed to hardcode the string https://radar.com/ref/go/84/ - including escape characters and everything, then all works fine. No issues. If I handle a normal string incoming without escape characters it stores fine in the singleton as well, no issue. enter code here
I am pretty stumped here as to what is going on. Can someone assist?
Thank you
For URL you received as string you need to encode before use it to in your app. Have a look at below code:
NSString *sampleUrl = #"https:\/\/radar.com\/ref\/go\/84\/";
NSString *encodedUrl = [sampleUrl stringByAddingPercentEscapesUsingEncoding:
NSUTF8StringEncoding];

Dictionary initialized in AppDelegate has nil value in UIViewController

I am using open weather API to get live weather data and displaying it in a UIViewController. However I make the http request in AppDelegate. So I made the API request in AppDelegate in a method called weatherForcast(), converted the JSON response to a NSDictionary object, and printed the object to the console just to make sure everything worked fine, and it did.
NSString *urllink = [NSString stringWithFormat:#"http://api.openweathermap.org/data/2.5/weather?lat=%f&lon=%f&appid=%#&units=metric", lat, lng, WEATHERAPIKEY];
NSURL *jsonURL = [NSURL URLWithString:[self urlEncodeValue:urllink]];
NSString *jsonDataString = [[NSString alloc]initWithContentsOfURL:jsonURL];
NSData *jsonData = [jsonDataString dataUsingEncoding:NSUTF16StringEncoding];
NSLog(#"This is jsonURL:%#", jsonURL);
NSError *err = nil;
if(jsonData == nil)
{
NSLog(#"Error laoding jsonData");
}
else
{
self.weatherInfo = [NSJSONSerialization JSONObjectWithData: jsonData options: NSJSONReadingMutableContainers error: &err];
NSLog(#"This is weatherInfo dictionary:%#", self.weatherInfo);
}
The dictionary is perfect.
Then in the UIViewController in viewDidLoad I call the method weatherForecast() and then call a method UpdateTemperature() which sets all the texts of the labels to data in the dictionary. Here is the code in the method UpdateTemperature:
NSLog(#"This is the weatherInfo dictionary: %#", appDel.weatherInfo);
if([appDel.weatherInfo count] > 0 && appDel.isNetworkAvailable)
{
NSLog(#"Went into weatherInfo.count > 0");
lblCondition.text = [NSString stringWithFormat:#"condition:%#", [[[appDel.weatherInfo valueForKey:#"weather"] objectAtIndex:0] valueForKey:#"description"]];
lblHumidity.text = [NSString stringWithFormat:#"humidity:%#", [[appDel.weatherInfo valueForKey:#"main"] valueForKey:#"humidity"]];
lblTemperature.text = [NSString stringWithFormat:#"%# Celsius", [[appDel.weatherInfo valueForKey:#"main"] valueForKey:#"temp"]];
imgWeather.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#%#", WEATHERCONDITIONIMGURL, [appDel.weatherInfo valueForKey:#"icon"]]]]];
lblDegree.hidden = FALSE;
[getTemp stopAnimating];
}
else
{
lblDegree.hidden = TRUE;
}
All the labels will only be set if the dictionary has at least one object within it, which it should. But it turned not not too. So I printed the dictionary, and got nil.
In AppDelegate when I printed the dictionary it was fine, but than in viewDidLoad when I printed the same dictionary it turned out to be nil. What is happening?
It's likely that when viewDidLoad gets called, weatherInfo has not been initialized yet. If it requires an http call the data may have not returned yet and therefore when you access it in viewDidLoad there is no object to access. You might want to try reconfiguring where you make your http request and create weatherInfo.
when you create object of appdelegate then all variable of appdelegate is reinitialized so it return nil. Just put your code into a fuction and simply return a dictionary
plz try this,
-(NSDictionary *) getWeatherInfo
{
NSString *urllink = [NSString stringWithFormat:#"http://api.openweathermap.org/data/2.5/weather?lat=%f&lon=%f&appid=%#&units=metric", 10.0, 10.0, #"api"];
NSURL *jsonURL = [NSURL URLWithString:[self urlEncodeValue:urllink]];
NSData *jsonData = [NSData dataWithContentsOfURL:jsonURL];
NSLog(#"This is jsonURL:%#", jsonURL);
NSError *err = nil;
NSDictionary *weather_info=[NSDictionary dictionary];
if(jsonData == nil)
{
NSLog(#"Error laoding jsonData");
}
else
{
weather_info = [NSJSONSerialization JSONObjectWithData: jsonData options: NSJSONReadingMutableContainers error: &err];
NSLog(#"This is weatherInfo dictionary:%#", weather_info);
}
return weather_info;
}

JSON Parsing text are In Encoded Form

I am a newbie in iOS development. I parsed a JSON Data From URL like as:
http://www.janvajevu.com/webservice/specific_post.php?post_id=2885
And I parsed a JSON data from it like as:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.webSpinner startAnimating];
NSURL * url=[NSURL URLWithString:[NSString stringWithFormat:#"http://www.janvajevu.com/webservice/specific_post.php?post_id=2885"]];
dispatch_async(kBgQueue, ^{
data = [NSData dataWithContentsOfURL: url];
[self performSelectorOnMainThread:#selector(fetchedData:) withObject:data waitUntilDone:YES];
});
}
-(void)fetchedData:(NSData *)responsedata
{
if (responsedata.length > 0)
{
NSError* error;
self.webDictionary= [NSJSONSerialization JSONObjectWithData:responsedata options:kNilOptions error:&error];
self.webArray=[_webDictionary objectForKey:#"data"];
}
self.headingString=[self.webArray valueForKey:#"post_title"];
NSLog(#"Web String %#",self.headingString);
[self.webSpinner stopAnimating];
self.webSpinner.hidesWhenStopped=TRUE;
NSString *headingString=[NSString stringWithFormat:#"%#",self.headingString];
NSCharacterSet *charsToTrim = [NSCharacterSet characterSetWithCharactersInString:#"() \n\""];
self.headLabel.text=[headingString stringByTrimmingCharactersInSet:charsToTrim];
}
Then I got a response like as means I got label text as:
"\U0aaa\U0abe\U0a97\U0ab2 \U0aae\U0abe\U0ab8\U0acd\U0aa4\U0ab0"
And when I parsed English letters from like as here in my URL "author_name" contain English letters when I parsed it then it print as same as in JSON data but other language means here my URL other data contain Gujarati letters then it is parsed in to decoded or not in Gujarati letters.
Here I not encoded my URL in my code then how it come in this format? Please give me solution for it.
You need to convert ASCII(Unicode Escaped) to Unicode(UTF-8).
check this : http://www.rapidmonkey.com/unicodeconverter/reverse.jsp
In first text box put your \U0aaa... text and click convert you will get what you want.
Now how you can do this in Objective-C:
Try this and let me know what you get.
NSData *data = [self dataUsingEncoding:[NSString defaultCStringEncoding]];
NSString *unicodeString = [[NSString alloc] initWithData:data encoding:NSNonLossyASCIIStringEncoding];
self.headLabel.text = asciiString;
try this
NSString *aDescription = self.webArray[0][#"post_title_slug"];
NSString *aTitle = [[aDescription stringByRemovingPercentEncoding] stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];

NSUTF8StringEncoding gives me this %0A%20%20%20%20%22http://example.com/example.jpg%22%0A

I'm trying to load pictures from twitter. If i just use the URL in the json results without encoding, in the dataWithContentsOfURL, I get nil URL argument. If I encode it, I get as follow's
%0A%20%20%20%20%22http://example.com/example.jpg%22%0A.
I know I can use rangeOfString: or stringByReplacingOccurrencesOfString: but can I be sure that it will always be the same, is there another way to handle this, and why is this happening to my twitter response and not my instagram response?
I have also tried
stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]
and it does nothing.
This is the URL directly from the json...
2013-11-08 22:09:31:812 JaVu[1839:1547] -[SingleEventTableViewController tableView:cellForRowAtIndexPath:] [Line 406] (
"http://pbs.twimg.com/media/BYWHiq1IYAAwSCR.jpg"
)
Here is my code
if ([post valueForKeyPath:#"entities.media.media_url"]) {
NSString *twitterString = [[NSString stringWithFormat:#"%#", [post valueForKeyPath:#"entities.media.media_url"]]stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
twitterString = [twitterString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(#"%#", twitterString);
if (twitterString != nil){
NSURL *twitterPhotoUrl = [NSURL URLWithString:twitterString];
NSLog(#"%#", twitterPhotoUrl);
dispatch_queue_t queue = kBgQueue;
dispatch_async(queue, ^{
NSError *error;
NSData* data = [NSData dataWithContentsOfURL:twitterPhotoUrl options:NSDataReadingUncached error:&error];
UIImage *image = [UIImage imageWithData:data];
dispatch_sync(dispatch_get_main_queue(), ^{
[streamPhotoArray replaceObjectAtIndex:indexPath.row withObject:image];
cell.instagramPhoto.image = image;
});
});
}
}
The log output you show appears to be an array, since it has parentheses with the string on a separate line.
You shouldn't need to encode the string if it's already a valid URL string and in fact doing so is wrong and will break things.
%0A%20%20%20%20%22 stands for a \n followed by 4 spaces and then ". This is in accordance with the description in the console. Have you used NSJSONSerialization to obtain the URL from JSON data?
Not the answer rather a step in solving the error,: Change your code to this and post the output. Combining several method calls in one makes debugging harder.
NSLog(#"post: '%#", post);
NSString * twitterString;
twitterString = [post valueForKeyPath:#"entities.media.media_url"];
NSLog(#"twitterString 1: '%#", twitterString);
twitterString = [twitterString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(#"twitterString 2: '%#", twitterString);
twitterString = [twitterString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(#"twitterString 3: '%#", twitterString);
BTW, [NSString stringWithFormat:#"%#"... is not necessary.

Count how many of a certain object appear in a JSON query

I'm returning JSON with a rough structure like the one below, and I'm trying to figure out how I can count how many platforms there are (in this case, three, but could be anything from 1 to 20 or so). I've returned the JSON into an NSDictionary and am using lines such as these to retrieve the data I need:
_firstLabel.text = _gameDetailDictionary[#"results"][#"name"];
In the above case, it'll grab the name from the results section. Since there are multiple platforms, I need to construct a loop to cycle through each name inside the platforms section. Not too sure how to go about that. All help appreciated!
"results":{
"platforms":[
{
"api_detail_url":"http://",
"site_detail_url":"http://",
"id":18,
"name":"First Name"
},
{
"api_detail_url":"http://",
"site_detail_url":"http://",
"id":116,
"name":"Second Name"
},
{
"api_detail_url":"http://",
"site_detail_url":"http://",
"id":22,
"name":"Third Name"
}
],
EDIT: Here's my fetchJSON method:
- (NSDictionary *) fetchJSONDetail: (NSString *) detailGBID {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible: YES];
NSString *preparedDetailURLString = [NSString stringWithFormat:#"http://whatever/format=json", detailGBID];
NSLog(#"Doing a detailed search for game ID %#", detailGBID);
NSData *jsonData = [NSData dataWithContentsOfURL: [NSURL URLWithString:preparedDetailURLString]];
_resultsOfSearch = [[NSDictionary alloc] init];
if (jsonData) {
_resultsOfSearch = [NSJSONSerialization JSONObjectWithData: jsonData
options: NSJSONReadingMutableContainers
error: nil];
}
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible: NO];
NSString *results = _resultsOfSearch[#"number_of_page_results"];
_numberOfSearchResults = [results intValue];
NSArray *platforms = [_resultsOfSearch valueForKey:#"platforms"];
int platformsCount = [platforms count];
NSLog(#"This game has %d platforms!", platformsCount);
return _resultsOfSearch;
}
The "platforms" JSON field is an array, so assuming you've de-serialised the JSON using something like,
NSMutableDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:resultsData options:NSJSONReadingMutableContainers error:&error];
Then, you can assign platforms to an NSArray,
NSDictionary *results = [responseJSON valueForKey:#"results"];
NSArray *platforms = [results valueForKey:#"platforms"];
...and find the number of platforms via,
int platformsCount = [platforms count];
In your case, where you want to iterate through the platforms, you can use,
for (NSDictionary *platform in platforms)
{
// do something for each platform
}

Resources