I am using the Google Directions iOS API. I am getting the data using JSON instead of XML. But I am using AFNetworking to simplify this for me. AFNetworking is available at github. Right now, I am able to display an overlay route from one location to another on an MKMapView. Here is my code:
// AFNETWORKING ==========================================================
AFHTTPClient *_httpClient = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:#"http://maps.googleapis.com/"]];
[_httpClient registerHTTPOperationClass: [AFJSONRequestOperation class]];
[_httpClient setDefaultHeader:#"Accept" value:#"application/json"];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
[parameters setObject:[NSString stringWithFormat:#"%f,%f", location.coordinate.latitude, location.coordinate.longitude] forKey:#"origin"];
[parameters setObject:[NSString stringWithFormat:#"%f,%f", location2.coordinate.latitude, location2.coordinate.longitude] forKey:#"destination"];
[parameters setObject:#"false" forKey:#"sensor"];
[parameters setObject:#"driving" forKey:#"mode"];
[parameters setObject:#"metric" forKey: #"units"];
NSMutableURLRequest *request = [_httpClient requestWithMethod:#"GET" path: #"maps/api/directions/json" parameters:parameters];
request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
AFHTTPRequestOperation *operation = [_httpClient HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSInteger statusCode = operation.response.statusCode;
if (statusCode == 200) {
[self parseResponse:responseObject];
} else {
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { }];
[_httpClient enqueueHTTPRequestOperation:operation];
// ROUTE SETUP AND RESPONSE RECIEVED METHOD ==========================================================
- (void)parseResponse:(NSDictionary *)response {
NSArray *routes = [response objectForKey:#"routes"];
NSDictionary *routePath = [routes lastObject];
if (routePath) {
NSString *overviewPolyline = [[routePath objectForKey: #"overview_polyline"] objectForKey:#"points"];
NSLog(#"Status: %#", [response objectForKey: #"status"]);
NSLog(#"Legs: %#", [routePath objectForKey: #"legs[]"]);
_path = [self decodePolyLine:overviewPolyline];
NSInteger numberOfSteps = _path.count;
CLLocationCoordinate2D coordinates[numberOfSteps];
for (NSInteger index = 0; index < numberOfSteps; index++) {
CLLocation *location = [_path objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
coordinates[index] = coordinate;
}
polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps];
[self.mapView addOverlay:polyLine];
}
}
This is the main code to get the route functioning. And it works well! But now what I want to do is get direction list and complete duration and summary. So I took a deep look at Google Directions API Documentation and it tells me to use its different dictionaries and arrays and objects. But I have had no luck. I get a status of OK. When I log the count of the routes array, its only one object. Then the MOST important, legs[] array is NULL.
NSLog(#"Legs is: %#", [routePath objectForKey: #"legs[]"]);
Output:
Legs is (null)
Legs[] includes everything important like the direction list and duration. Summary is not NULL, it gives the name of one of the streets that the route bypasses. I dont know how that is a summary. Might be because there is only one object in the routes array. waypoint_order and warnings[] are NULL too. bounds and of course overview_polyline are valid, thats how I got the route working.
So whats the problem here? Why are so many of the objects Google Directions API provides NULL when I need them?
Thanks!
Alright, the problem was that the response for directions was taking too long. I expected the legs[] response to instantly deliver along with the overview_polyline. So I just had to wait till the response came in, this gives me an opportunity to insert a buffer UI.
Related
I've just started using the new AFNetworking 2.0 API having used the previous versions for a while now. I'm trying to do a bog standard http POST request, but sadly I'm not doing too well. This is my current code:
AFHTTPRequestOperationManager *operationManager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"username" : self.usernameField.text,
#"password" : self.passwordField.text};
[operationManager POST:#"https:URL GOES HERE" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", [responseObject description]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
Now this returns a JSON of (NULL) and doesn't give me a status code like 404 or something (incidentally how do we attain the status code when using AFN 2.0?). However, when I try the information with a web app like apikitchen.com which tests the HTTP Post request for me, it works when I put the username and password in the param field. So really my question is, why don't the parameters in the AFN 2.0 parameter property act in the same way as the parameters in the web app? And more generally why aren't the post request parameters working for me in AFN 2.0?
Thanks for the help in advance,
Mike
EDIT: I'm struggling with the implementation of the suggested fix. My Post method now looks like this, but It doesn't make sense to me right now.
AFHTTPRequestOperationManager *operationManager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"username" : self.usernameField.text,
#"password" : self.passwordField.text};
operationManager.requestSerializer.queryStringSerializationWithBlock =
^NSString*(NSURLRequest *request,
NSDictionary *parameters,
NSError *__autoreleasing *error) {
NSString* encodedParams = form_urlencode_HTTP5_Parameters(parameters);
return encodedParams;
};
[operationManager POST:#"URL HERE" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", [responseObject description]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
Now this returns a JSON of (NULL) and doesn't give me a status code like 404 or something (incidentally how do we attain the status code when using AFN 2.0?).
It should at least give an error. What does the failure handler print out?
So really my question is, why don't the parameters in the AFN 2.0 parameter property act in the same way as the parameters in the web app? And more generally why aren't the post request parameters working for me in AFN 2.0?
After examining how AFN (Version 2.0.1) encodes the parameters, it appears to me that these aren't encoded as they should: The application/x-www-form-urlencoded encoding algorithm.
Until this has been fixed, you may try the following workaround. The following algorithm encodes parameters strictly as suggested by w3c for HTTP 5, at least for Mac OS X 10.8 where I've tested it:
static NSString* form_urlencode_HTTP5_String(NSString* s) {
CFStringRef charactersToLeaveUnescaped = CFSTR(" ");
CFStringRef legalURLCharactersToBeEscaped = CFSTR("!$&'()+,/:;=?#~");
NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
kCFAllocatorDefault,
(__bridge CFStringRef)s,
charactersToLeaveUnescaped,
legalURLCharactersToBeEscaped,
kCFStringEncodingUTF8));
return [result stringByReplacingOccurrencesOfString:#" " withString:#"+"];
}
(Note: the code above depends on the implementation details of function CFURLCreateStringByAddingPercentEscapes. It's entirely possible to implement the suggested algorithm easily without any dependencies, which I would recommend - it becomes just not that short.)
static NSString* form_urlencode_HTTP5_Parameters(NSDictionary* parameters)
{
NSMutableString* result = [[NSMutableString alloc] init];
BOOL isFirst = YES;
for (NSString* name in parameters) {
if (!isFirst) {
[result appendString:#"&"];
}
isFirst = NO;
assert([name isKindOfClass:[NSString class]]);
NSString* value = parameters[name];
assert([value isKindOfClass:[NSString class]]);
NSString* encodedName = form_urlencode_HTTP5_String(name);
NSString* encodedValue = form_urlencode_HTTP5_String(value);
[result appendString:encodedName];
[result appendString:#"="];
[result appendString:encodedValue];
}
return [result copy];
}
Then, when using AFN, you can customize the serializing algorithm as shown below:
AFHTTPRequestOperationManager *operationManager = [AFHTTPRequestOperationManager manager];
operationManager.requestSerializer.queryStringSerializationWithBlock =
^NSString*(NSURLRequest *request,
NSDictionary *parameters,
NSError *__autoreleasing *error) {
NSString* encodedParams = form_urlencode_HTTP5_Parameters(parameters);
return encodedParams;
};
Put / after the url. I've missed it for hours.
I am trying to build a simple application using MapKit that will automatically search for a specific place when the app launches and drop pin(s) on the map at the locations(s). I am seeing all sorts of ways to load locations (lat/lon, etc), but nothing that lets me search for a specific business name, restaurant name, etc.
I am expecting to work with Apple Maps. However, if Google Maps would be a better solve than so be it.
Any help would be appreciated. Thanks
iOS >= 6.1 provides MKLocalSearch, MKLocalSearchRequest to search for natural language points of interest. Sample
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.region = regionToSearchIn;
request.naturalLanguageQuery = #"restaurants"; // or business name
MKLocalSearch *localSearch = [[MKLocalSearch alloc] initWithRequest:request];
[localSearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
// do something with the results / error
}];
i know its late but hope this helps!
[super viewDidLoad];
[self.searchDisplayController setDelegate:self];
[self.ibSearchBar setDelegate:self];
self.ibMapView.delegate=self;
// Zoom the map to current location.
[self.ibMapView setShowsUserLocation:YES];
[self.ibMapView setUserInteractionEnabled:YES];
[self.ibMapView setUserTrackingMode:MKUserTrackingModeFollow];
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.delegate=self;
[locationManager startUpdatingLocation];
[self.ibMapView setRegion:MKCoordinateRegionMake(locationManager.location.coordinate, MKCoordinateSpanMake(0.2, 0.2))];
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.region = self.ibMapView.region;
request.naturalLanguageQuery = #"restaurant";
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
localSearch = [[MKLocalSearch alloc] initWithRequest:request];
[localSearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error){
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
results = response;
if (response.mapItems.count == 0)
NSLog(#"No Matches");
else
for (MKMapItem *item in response.mapItems)
{
NSLog(#"name = %#", item.name);
NSLog(#"Phone = %#", item.phoneNumber);
[_matchingItems addObject:item];
MKPointAnnotation *annotation =
[[MKPointAnnotation alloc]init];
annotation.coordinate = item.placemark.coordinate;
annotation.title = item.name;
[self.ibMapView addAnnotation:annotation];
}
}];
}
Make the following steps to display nearest places.
Using google API find the Nearest Places Google Places API
The google API provide LAt and Long and address Informations.
Then Store the LAt and Long Values to Array then USing this lat and long values you can display Annotations in Apple map (iOS 6+) and Google Map (iOS 5).
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Forward Geocode Example using CLGeocoder
I have a plist full of names and their adrresses. I want my iOS app to show on a map view a pin with the address of the person he has selected. Can I import the address to map view and get a pin? And how?? Thank you.
Use the CLGeocoder class to convert addresses into lat/long coordinates:
Forward Geocode Example using CLGeocoder
The more accurate address you have, the better the result should be so with exact addresses you should get very accurate points.
Another option is to use Google's geocoding web service, simply pass the address string to this function and you will get an CLLocationCoordinate2D which contains a latitude & longitude.
Right now it grabs the location at the 0th index, which is the closest matching result. Log out the result to see the JSON response from Google.
- (CLLocationCoordinate2D) geoCodeUsingAddress:(NSString *)address
{
NSString *esc_addr = [address stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *req = [NSString stringWithFormat:#"http://maps.google.com/maps/api/geocode/json?sensor=true&address=%#", esc_addr];
CLLocationCoordinate2D center;
NSString *result = [NSString stringWithContentsOfURL:[NSURL URLWithString:req] encoding:NSUTF8StringEncoding error:NULL];
if (result)
{
//NSLog(#"LOC RESULT: %#", result);
NSError *e;
NSDictionary *resultDict = [NSJSONSerialization JSONObjectWithData: [result dataUsingEncoding:NSUTF8StringEncoding]
options: NSJSONReadingMutableContainers
error: &e];
NSArray *resultsArray = [resultDict objectForKey:#"results"];
if(resultsArray.count > 0)
{
resultDict = [[resultsArray objectAtIndex:0] objectForKey:#"geometry"];
resultDict = [resultDict objectForKey:#"location"];
center.latitude = [[resultDict objectForKey:#"lat"] floatValue];
center.longitude = [[resultDict objectForKey:#"lng"] floatValue];
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"No Results Found" message:#"No locations were found using, please try again." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[alert show];
}
//goes through each result
/*for(NSDictionary *dict in resultsArray)
{
resultDict = [dict objectForKey:#"geometry"];
resultDict = [resultDict objectForKey:#"location"];
}*/
}
return center;
}
This is whats known as Forward Geocoding, and there is no built in API to do this for you. You need to use an external service, which one you use really depends on your app.
I have used Google's service for this. http://code.google.com/apis/maps/documentation/geocoding/
It is a very simple API, but has restrictions based on your app's license. I know there are a couple other services for this, but I'll leave that as an exercise to you.
I'm afraid I'm a newbie to objective-c programming, and I am having a problem that I have spent all day trying to figure out and I cannot, so I am humbly asking you guys if anyone can help.
I am trying to read the details from a JSON page online (for instance a local services directory) and have installed the JSON library into Xcode and it seems to work fine. I'm developing for the iPhone by the way, and have the latest versions all installed.
The problem is, what with me being a newb and all, I seem unable to retrieve all the information I need from the JSON file.
the JSON data I am testing with is this:
"testlocal_response" = {
header = {
query = {
business = newsagent;
location = brighton;
page = 1;
"per_page" = 1;
"query_path" = "business/index";
};
status = ok;
};
records = (
{
address1 = "749 Rwlqsmuwgj Jcyv";
address2 = "<null>";
"average_rating" = 0;
"business_id" = 4361366;
"business_keywords" = "<null>";
"business_name" = "Gloucester Newsagents";
"data_provider_id" = "<null>";
"display_details" = "<null>";
"distance_in_miles" = "0.08";
fax = "<null>";
gridx = "169026.3";
gridy = "643455.7";
"image_url" = "<null>";
latitude = "50.82718";
"logo_path" = Deprecated;
longitude = "-0.13963";
phone = 97204438976;
postcode = "IY1 6CC";
"reviews_count" = 0;
"short_description" = "<null>";
"touch_url" = "http://www.test.com/business/list/bid/4361366";
town = BRIGHTON;
url = "<null>";
}
);
};
}
Now, in my code ViewController.m page, in the 'connectionDidFinishLoading' area I have added:
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[responseData release];
// make sure JSON has all been pulled in
NSLog(#"This is from the JSON page:\n");
NSLog(responseString);
NSError *error;
SBJSON *json = [[SBJSON new] autorelease];
// using either of these seems to make no difference?
NSDictionary *touchDirect = [json objectWithString:responseString error:&error];
//NSArray *touchDirect = [json objectWithString:responseString error:&error];
[responseString release];
if (touchDirect == nil)
label.text = [NSString stringWithFormat:#"JSON parsing failed: %#", [error localizedDescription]];
else {
NSMutableString *text = [NSMutableString stringWithString:#"Test directory details:\n"];
[text appendFormat:#"%#\n", [[[[touchDirect objectForKey:#"testlocal_response"] objectForKey:#"header"] objectForKey:#"query"] objectForKey:#"business"]];
label.text = text;
Testing this I get the value for the business ('newsagent') returned, or location ('brighton') which is the correct. My problem is, I cannot go further into the JSON. I don't know how to pull out the result for the actual 'records' which, in the test example there is only one of but can be more divided using brackets '(' and ')'.
As soon as I try to access the data in these record areas (such as 'address1' or 'latitude' or 'postcode') it fails and tells me 'unrecognized selector sent to instance'
PLEASE can anyone tell me what I'm doing wrong?! I've tried so many different things and just cant get any further! I've read all sorts of different things online but nothing seems to help me.
Any replies deeply appreciated. I posted up a question on iPhone SDK too but havent had a useful response yet.
many thanks,
-Robsa
Have you validated your JSON?
It's not clear how you are trying to access the objects that you say are erroring. The specific line(s) you are having trouble with would be helpful.
It's usually easier to set a pointer to the dictionary you are going to be accessing for readability..
NSDictionary *records = [[objectForKey:#"testlocal_response"] objectForKey#"records"];
then...
NSString *businessName = [records objectForKey:#"business_name"];
float latitude = [[records objectForKey:#"latitude"] floatValue];
Well, I finally sorted it out! I put the records in an NSString, which I could then access using objectAtIndex.
Here is the main Viewcontroller.m code for it:
- (void)viewDidLoad {
[super viewDidLoad];
responseData = [[NSMutableData data] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"*URL TO JSON DATA HERE*"]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
NSMutableArray *touchDirect = [json objectWithString:responseString error:&error];
NSString *touchRecord = [[touchDirect objectForKey:#"touchlocal_response"] objectForKey:#"records"];
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
label.text = [NSString stringWithFormat:#"Connection failed: %#", [error description]];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[responseData release];
NSError *error;
SBJSON *json = [[SBJSON new] autorelease];
//Retrieves the JSON header Data, returning info such as 'status' [which should return 'ok']
NSMutableArray *touchDirect = [json objectWithString:responseString error:&error];
//Puts the records returned into a string called touchRecord
NSString *touchRecord = [[touchDirect objectForKey:#"touchlocal_response"] objectForKey:#"records"];
[responseString release];
// test results
[text appendFormat:#" Address: %#\n", [[touchRecord objectAtIndex:0] objectForKey:#"address1"]];
[text appendFormat:#" Phone: %#\n", [[touchRecord objectAtIndex:0] objectForKey:#"phone"]];
[text appendFormat:#" Address Data record 2: %#\n", [[touchRecord objectAtIndex:1] objectForKey:#"address1"]];
[text appendFormat:#" Phone Data record 2: %#\n", [[touchRecord objectAtIndex:1] objectForKey:#"phone"]];
This now seems to work fine. I also have a if..else if statement to catch errors now. Does this code look Ok?
Thanks for the tip, Nick - I was just trying to get the output right before tidying the code up. I am using an NSMutableArray to put my JSON into initially, is this OK? What is the benefit of putting it into an NSDictionary?
regards,
Robsa
I have an application that needs to have a similar search feature like the Apple "Maps" application (included with iPhone, iPod Touch and iPad).
The feature in question should not be a hard thing to do, but I'm really clueless about how to input a Street Address in the search bar, and then obtaining coordinates for that address or something that can help me to actually move the map and center in that place.
I mean, what do I have to query, does Apple provide an "address searching API method" ? or I need to use the google maps API directly ?
I would love to hear how should it be done.
Ok, to answer my own question:
As was mentioned before, the best thing to do is to use the Google Maps API,
it supports a lot of formats but for several reasons I chose to go with JSON.
So here are the steps to perform a JSON query to Google Maps and obtain the coordinate of the query. Note that not all the correct validations are done, this is only a Proof of concept.
1) Download a JSON framework/library for the iPhone, there are several, I chose to go with this one, it's very good and seems an active project, plus several comercial applications seem to be using it. So add it to your project ( instructions here ).
2) To query Google Maps for an address we need to build a request URL like this:
http://maps.google.com/maps/geo?q=Paris+France
This url, will return a JSON object for the query "Paris+France".
3) Code:
//Method to handle the UISearchBar "Search",
- (void) searchBarSearchButtonClicked:(UISearchBar *)theSearchBar
{
//Perform the JSON query.
[self searchCoordinatesForAddress:[searchBar text]];
//Hide the keyboard.
[searchBar resignFirstResponder];
}
After we handle the UISearchBar search, we must make the request to Google Maps:
- (void) searchCoordinatesForAddress:(NSString *)inAddress
{
//Build the string to Query Google Maps.
NSMutableString *urlString = [NSMutableString stringWithFormat:#"http://maps.google.com/maps/geo?q=%#?output=json",inAddress];
//Replace Spaces with a '+' character.
[urlString setString:[urlString stringByReplacingOccurrencesOfString:#" " withString:#"+"]];
//Create NSURL string from a formate URL string.
NSURL *url = [NSURL URLWithString:urlString];
//Setup and start an async download.
//Note that we should test for reachability!.
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection release];
[request release];
}
We must of course then handle the response of the GoogleMaps server ( Note: a lot of validations missing)
//It's called when the results of [[NSURLConnection alloc] initWithRequest:request delegate:self] come back.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
//The string received from google's servers
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
//JSON Framework magic to obtain a dictionary from the jsonString.
NSDictionary *results = [jsonString JSONValue];
//Now we need to obtain our coordinates
NSArray *placemark = [results objectForKey:#"Placemark"];
NSArray *coordinates = [[placemark objectAtIndex:0] valueForKeyPath:#"Point.coordinates"];
//I put my coordinates in my array.
double longitude = [[coordinates objectAtIndex:0] doubleValue];
double latitude = [[coordinates objectAtIndex:1] doubleValue];
//Debug.
//NSLog(#"Latitude - Longitude: %f %f", latitude, longitude);
//I zoom my map to the area in question.
[self zoomMapAndCenterAtLatitude:latitude andLongitude:longitude];
[jsonString release];
}
Finally the function to zoom my map, which should by now be a trivial thing.
- (void) zoomMapAndCenterAtLatitude:(double) latitude andLongitude:(double) longitude
{
MKCoordinateRegion region;
region.center.latitude = latitude;
region.center.longitude = longitude;
//Set Zoom level using Span
MKCoordinateSpan span;
span.latitudeDelta = .005;
span.longitudeDelta = .005;
region.span = span;
//Move the map and zoom
[mapView setRegion:region animated:YES];
}
Hope this helps someone because the JSON part was a real pain to figure out, the library is not very well documented in my opinion, still it's very good.
EDIT:
Modified one method name to "searchCoordinatesForAddress:" because of #Leo question. I have to say that this method is good as a proof of concept but if you plan to download big JSON files , you will have to append to a NSMutableData object to hold all the query to the google server. ( remember that HTTP queries come by pieces . )
This link helps you if you search a region.
NSMutableString *urlString = [NSMutableString stringWithFormat:#"http://maps.google.com/maps/geo?q=%#?output=json",inAddress];
If you want to search a street this is the corect link
NSMutableString *urlString = [NSMutableString stringWithFormat:#"http://maps.google.com/maps/geo?q=%#&output=json",inAddress];
Notice that the 2nd ? should be &.
Swift version, adapted for iOS 9:
let geocoder = CLGeocoder()
geocoder.geocodeAddressString(addressString) { (placemarks, error) in
if let center = (placemarks?.first?.region as? CLCircularRegion)?.center {
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpanMake(0.02, 0.02))
self.mapView.setRegion(region, animated: true)
}
}
based on user1466453's answer.
If anyone else is having the same issue, heres the link:
https://github.com/stig/json-framework/
scroll down to Project renamed to SBJson
Also, here is the code for getting all the data before your app uses it. Note the delegate method 'did receive data' as it appends the mutable data object with the downloaded data.
I JUST USED MR GANDOS searchCoodinatesMETHOD AS IT IS AS IT WORKS WELL
- (void) searchCoordinatesForAddress:(NSString *)inAddress
{
//Build the string to Query Google Maps.
NSMutableString *urlString = [NSMutableString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?address=%#&sensor=false",inAddress];
//Replace Spaces with a '+' character.
[urlString setString:[urlString stringByReplacingOccurrencesOfString:#" " withString:#"+"]];
//Create NSURL string from a formate URL string.
NSURL *url = [NSURL URLWithString:urlString];
//Setup and start an async download.
//Note that we should test for reachability!.
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection release];
[request release];
}
// STEP ONE
// THIS ONE IS IMPORTANT AS IT CREATES THE MUTABLE DATA OBJECT AS SOON AS A RESPONSE IS RECEIVED
-(void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
{
if (receivedGeoData)
{
[receivedGeoData release];
receivedGeoData = nil;
receivedGeoData = [[NSMutableData alloc] init];
}
else
{
receivedGeoData = [[NSMutableData alloc] init];
}
}
/// STEP TWO
// THIS ONE IS IMPORTANT AS IT APPENDS THE DATA OBJECT WITH THE DATA
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[receivedGeoData appendData:data];
}
// STEP THREE......
// NOW THAT YOU HAVE ALL THE DATA MAKE USE OF IT
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString *jsonResult = [[NSString alloc] initWithData:receivedGeoData encoding:NSUTF8StringEncoding];
NSError *theError = NULL;
dictionary = [NSMutableDictionary dictionaryWithJSONString:jsonResult error:&theError];
NSLog(#"%#",dictionary);
int numberOfSites = [[dictionary objectForKey:#"results"] count];
NSLog(#"count is %d ",numberOfSites);
}
-(void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
{
// Handle the error properly
}
You can use Google's API service to get lat/long coords from a textual search string. Be sure to pass the user's current location so the results are relevant. Read the answers to this question: Search and display business locations on MKMapView