I want to send the city name to the server. I am getting latitude longitude using CLLocationManager. Then I use this link to do reverse geocoding.
https://maps.googleapis.com/maps/api/geocode/json?latlng=lati,longi&key=myApiKey
My problem is for different locations the number of address components are different. As an example, I am getting this array of address componeents for my current location.
"results": [
{
"address_components": [
{
"long_name": "ABC Rd",
"short_name": "ABC Rd",
"types": [
"route"
]
},
{
"long_name": "My City",
"short_name": "My City",
"types": [
"administrative_area_level_2",
"political"
]
},
{
"long_name": "My Province",
"short_name": "AB",
"types": [
"administrative_area_level_1",
"political"
]
},
{
"long_name": "My Country",
"short_name": "MC",
"types": [
"country",
"political"
]
}
],
For my client's location im getting this
results": [
{
"address_components": [
{
"long_name": "4",
"short_name": "4",
"types": [
"street_number"
]
},
{
"long_name": "some name",
"short_name": "some name",
"types": [
"route"
]
},
{
"long_name": "some name",
"short_name": "Some name",
"types": [
"political",
"sublocality",
"sublocality_level_2"
]
},
{
"long_name": "some name",
"short_name": "some name",
"types": [
"political",
"sublocality",
"sublocality_level_1"
]
},
{
"long_name": "city",
"short_name": "city",
"types": [
"locality",
"political"
]
},
{
"long_name": "some name",
"short_name": "Some name",
"types": [
"administrative_area_level_1",
"political"
]
},
{
"long_name": "Client country",
"short_name": "CC",
"types": [
"country",
"political"
]
},
{
"long_name": "12345",
"short_name": "12345",
"types": [
"postal_code"
]
}
],
How can I get the exact city name for different locations when the address components are different. First I tried to get it my component index number but since number of components are different I cant do that. Whats the correct way to do that? Please help me.
Thanks
UPDATE
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(#"Found placemarks: %#, error: %#", placemarks, error);
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks objectAtIndex:0];
NSString *address = [NSString stringWithFormat:#"%# %#\n%# %#\n%#\n%#",
placemark.subThoroughfare, placemark.thoroughfare,
placemark.postalCode, placemark.subLocality,
placemark.subAdministrativeArea,
placemark.country];
// NSString *address=[self.placemark];
NSDictionary *dictAddress = [NSDictionary dictionaryWithDictionary:placemark.addressDictionary];
NSMutableDictionary *dictTxtData = [NSMutableDictionary dictionary];
NSLog(#"----LOCATION NAME----%#",[placemark.addressDictionary valueForKey:#"Name"]);
NSLog(#"-----STREET ADDRESS---%#",[placemark.addressDictionary valueForKey:#"Thoroughfare"]);
NSLog(#"-----CITY-----%#",[placemark.addressDictionary valueForKey:#"City"]);
strCountry=placemark.country;
NSLog(#"Address------%#",address);
} else {
NSLog(#"%#", error.debugDescription);
}
} ];
Results I get
----LOCATION NAME----My Rd
-----STREET ADDRESS---My Rd
-----CITY-----(null)
Address------(null) My Rd
(null) (null)
(null)
My Country
This is how I call to location update
-(void)GetLocationData
{
if (self.locationManager == nil)
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
}
else
{
nil;
}
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)])
{
[self.locationManager requestWhenInUseAuthorization];
}
else
{
nil;
}
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;//kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
}
The json responses from Google API can contain different place marks depending upon the location. Using index is not the correct approach. You can find the city name in json components where type is locality. Below is the code snippet
NSDictionary *locationData = [[json objectForKey:#"results"] objectAtIndex:0];
NSArray* addressComponents= [locationData objectForKey:#"address_components"];
//Iterate each result of address components - find locality and country
NSString *cityName;
for (NSDictionary* address in addressComponents)
{
NSArray* addressType = [address objectForKey:#"types"];
NSString* firstType = [addressType objectAtIndex:0];
if([firstType isEqualToString:#"locality"])
cityName = [address objectForKey:#"long_name"];
}
or you can also use CLGeocoder API in iOS.
CLGeocoder *ceo = [[CLGeocoder alloc]init];
CLLocation *loc = [[CLLocation alloc]initWithLatitude:lat longitude:long];
[ceo reverseGeocodeLocation: loc completionHandler:
^(NSArray *placemarks, NSError *error) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSLog(#"placemark %#",placemark.locality); // Get the city name
}];
call setLocation() in viewdidload method
func setLocation()
{
// self.view.backgroundColor = UIColor.whiteColor()
self.edgesForExtendedLayout = .None
// Set bounds to inner-west Sydney Australia.
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
// print("dofo \(manager.location?.coordinate.latitude)")
// print(manager.location?.coordinate.longitude)
currentlat = (manager.location?.coordinate.latitude)!
cuurentlong = (manager.location?.coordinate.longitude)!
let geoCoder = CLGeocoder()
let location = CLLocation(latitude: currentlat,
longitude: cuurentlong)
geoCoder.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in
// Place details
var placeMark: CLPlacemark!
placeMark = placemarks?[0]
// Address dictionary
print(placeMark.addressDictionary)
// Location name
if let locationName = placeMark.addressDictionary!["Name"] as? NSString {
print(locationName)
}
// Street address
if let street = placeMark.addressDictionary!["Thoroughfare"] as? NSString {
print(street)
}
// City
if let city = placeMark.addressDictionary!["City"] as? NSString {
print(city)
}
// Zip code
if let zip = placeMark.addressDictionary!["ZIP"] as? NSString {
print(zip)
}
// Country
if let country = placeMark.addressDictionary!["Country"] as? NSString {
print(country)
}
})
}
Related
I am getting an array from response as below
items=[{
"displayName": "Adam Codo",
"postedTime": "2011-04-04T21:31:20.000Z",
"message" : "Hello Test Message"
},
{
"displayName": "Leena",
"postedTime": "2011-04-04T20:32:20.000Z",
"message" : " Start Hello Test Message"
},
{
"displayName": "Zohn",
"postedTime": "2011-04-03T22:47:20.000Z",
"message" : "Hi Leena"
},
{
"displayName": "Leena",
"postedTime": "2011-04-04T21:32:20.000Z",
"message" : " Start Hello Test Message"
},
{
"displayName": "Adam Codo",
"postedTime": "2011-04-04T22:13:10.000Z",
"message" : "Hello Test Message"
}]
I have so sort the array by the name & later by the time. so I need sorted array like below
items=[
{
"displayName": "Adam Codo",
"postedTime": "2011-04-04T22:13:10.000Z",
"message" : "Hello reply Test Message"
},
{
"displayName": "Adam Codo",
"postedTime": "2011-04-04T21:31:20.000Z",
"message" : "Hello Test Message"
},
{
"displayName": "Leena",
"postedTime": "2011-04-04T21:32:20.000Z",
"message" : " Start Hello Test Message"
},
{
"displayName": "Leena",
"postedTime": "2011-04-04T20:32:20.000Z",
"message" : " Start Hello Test Message"
},
{
"displayName": "Zohn",
"postedTime": "2011-04-03T22:47:20.000Z",
"message" : "Hi Leena"
}
]
Can anyone suggest me how to do this? Any idea would be great.
Do NOT use dictionaries
Build your own model instead and life will be easier.
Here's the model
struct Element {
let displayName: String
let postedTime: Date
let message: String
init?(dict:[String:String]) {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
guard
let displayName = dict["displayName"],
let timeText = dict["postedTime"],
let postedTime = dateFormatter.date(from: timeText),
let message = dict["message"]
else { return nil }
self.displayName = displayName
self.postedTime = postedTime
self.message = message
}
}
Now let's make it Comparable
extension Element: Comparable {
static func <(lhs: Element, rhs: Element) -> Bool {
if lhs.displayName != rhs.displayName {
return lhs.displayName < rhs.displayName
}
return lhs.postedTime < rhs.postedTime
}
static func ==(lhs: Element, rhs: Element) -> Bool {
return lhs.displayName == rhs.displayName && lhs.postedTime < rhs.postedTime
}
}
Now given your array of dictionaries
let items = [
[
"displayName": "Adam Codo",
"postedTime": "2011-04-04T21:31:20.000Z",
"message" : "Hello Test Message"
],
[
"displayName": "Leena",
"postedTime": "2011-04-04T20:32:20.000Z",
"message" : " Start Hello Test Message"
],
[
"displayName": "Zohn",
"postedTime": "2011-04-03T22:47:20.000Z",
"message" : "Hi Leena"
],
[
"displayName": "Leena",
"postedTime": "2011-04-04T21:32:20.000Z",
"message" : " Start Hello Test Message"
],
[
"displayName": "Adam Codo",
"postedTime": "2011-04-04T22:13:10.000Z",
"message" : "Hello Test Message"
]
]
we can convert it to an array of Element(s) and finally sorting it
let sortedElms = items.flatMap(Element.init).sorted()
Result
[
Element(displayName: "Adam Codo", postedTime: 2011-04-04 21:31:20 +0000, message: "Hello Test Message"),
Element(displayName: "Adam Codo", postedTime: 2011-04-04 22:13:10 +0000, message: "Hello Test Message"),
Element(displayName: "Leena", postedTime: 2011-04-04 20:32:20 +0000, message: " Start Hello Test Message"),
Element(displayName: "Leena", postedTime: 2011-04-04 21:32:20 +0000, message: " Start Hello Test Message"),
Element(displayName: "Zohn", postedTime: 2011-04-03 22:47:20 +0000, message: "Hi Leena")
]
var sortedResults = items.sorted {
(dictOne, dictTwo) -> Bool in
if dictOne["displayName"]! != dictTwo["displayName"]! {
return dictOne["displayName"]! < dictTwo["displayName"]!
}
return dictOne["postedTime"]! < dictTwo["postedTime"]!
};
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey: #"displayName" ascending: YES];
NSArray *sortedArray = [_locations sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
NSArray *sortedLocations = [_locations sortedArrayUsingComparator: ^(NSDictionary *d1, NSDictionary *d2) {
ISO8601DateFormatter *formatter = [[ISO8601DateFormatter alloc] init];
NSDate *theDate1 = [formatter dateFromString:[d1 valueForKey:#"postedTime"]];
NSDate *theDate2 = [formatter dateFromString:[d2 valueForKey:#"postedTime"]];
return [theDate1 compare:theDate2];
}];
OR
NSArray *sortedLocations = [_locations sortedArrayUsingComparator: ^(NSDictionary *d1, NSDictionary *d2) {
ISO8601DateFormatter *formatter = [[ISO8601DateFormatter alloc] init];
NSDate *theDate1 = [formatter dateFromString:[d1 valueForKey:#"postedTime"]];
NSDate *theDate2 = [formatter dateFromString:[d2 valueForKey:#"postedTime"]];
NSString *name1 = [d1 valueForKey:#"displayName"];
NSString *name2 = [d2 valueForKey:#"displayName"];
if ([name1 compare:name2]) {
return [theDate1 compare:theDate2];
}
return NSOrderedDescending;
}];
But be awere I did not check it
I'm now got stuck that I cannot retrieve how to fetch value from below json of Google Place Detail API.
I want to get all data from "types" node.
{
"address_components" = (
{
"long_name" = "Bridge Street";
"short_name" = "Bridge St";
types = (
route
);
},
{
"long_name" = London;
"short_name" = London;
types = (
locality,
political
);
},
{
"long_name" = London;
"short_name" = London;
types = (
"postal_town"
);
},
{
"long_name" = "Greater London";
"short_name" = "Greater London";
types = (
"administrative_area_level_2",
political
);
},
{
"long_name" = "United Kingdom";
"short_name" = GB;
types = (
country,
political
);
},
{
"long_name" = "SW1A 2LW";
"short_name" = "SW1A 2LW";
types = (
"postal_code"
);
}
);
vicinity = London;
}
Why not integrate Google places API itself rather than parsing yourself.
It's simple and easy to retrieve places
here is the link
https://developers.google.com/places/ios-api/
You can use google places api. Use place id and use below code to get place details value.
-(id)getAddressFromPlaceId:(NSString*)placeId
{
NSString *placeRequest;
if ([AppDelegate getInstance].isDetailsLimitReached)
{
placeRequest = [[NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/details/json?placeid=%#&key=%#&language=en",placeId,[Utility getInstance].arrGooglkey[tempc]] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}
else
{
placeRequest = [[NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/details/json?placeid=%#&language=en",placeId] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:placeRequest]cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:20.0];
NSError *error;
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
if (error)
{
return nil;
}
else
{
NSDictionary *resData = [NSJSONSerialization JSONObjectWithData:response options:0 error:&error];
if (error)
{
return nil;
}
else
{
if ([resData[#"status"] isEqualToString:#"OK"] || [[resData objectForKey:#"status"] isEqualToString:#"ZERO_RESULTS"]) {
return [resData[#"result"] mutableCopy];
}
else
{
if ([AppDelegate getInstance].isDetailsLimitReached)
{
return nil;
}
[AppDelegate getInstance].isDetailsLimitReached = TRUE;
return [self getAddressFromPlaceId:placeId];
}
}
}
return nil;
}
I am trying following code to get google maps api response
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&sensor=false", saddr, daddr];
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSLog(#"api url: %#", apiUrl);
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSStringEncodingConversionAllowLossy error:Nil];
I got this apiResponse json data from google api:
{
"routes" : [
{
"bounds" : {
"northeast" : {
"lat" : 23.0236292,
"lng" : 72.60381579999999
},
"southwest" : {
"lat" : 22.990296,
"lng" : 72.5293059
}
},
"copyrights" : "Map data ©2015 Google",
"legs" : [
{
"distance" : {
"text" : "10.8 km",
"value" : 10797
},
"duration" : {
"text" : "23 mins",
"value" : 1403
},
"end_address" : "35, Shivranjani, Jodhpur, Ahmedabad, Gujarat 380015, India",
"end_location" : {
"lat" : 23.0234672,
"lng" : 72.5293059
},
"start_address" : "6, Natvarlal Raval Marg, Archana Society, Bhairavnath, Maninagar, Ahmedabad, Gujarat 380008, India",
"start_location" : {
"lat" : 22.990296,
"lng" : 72.60381579999999
},
"steps" : [
{
"distance" : {
"text" : "0.9 km",
"value" : 898
},
"duration" : {
"text" : "2 mins",
"value" : 123
},
"end_location" : {
"lat" : 22.9943614,
"lng" : 72.5962808
},
"html_instructions" : "Head \u003cb\u003enorthwest\u003c/b\u003e on \u003cb\u003eNatvarlal Raval Marg\u003c/b\u003e toward \u003cb\u003eNatvarlal Raval Marg\u003c/b\u003e\u003cdiv style=\"font-size:0.9em\"\u003ePass by Nelsons International School (on the right)\u003c/div\u003e",
"polyline" : {
"points" : "khikC{lczLMBu#jBSd#}AtDg#hA_#z#o#rAYl#O\\yArCgA|BMXQ`#q#bBm#zAcAjCSf#kArCMZ"
},
"start_location" : {
"lat" : 22.990296,
"lng" : 72.60381579999999
},
"travel_mode" : "DRIVING"
},
{
"distance" : {
"text" : "0.2 km",
"value" : 192
},
"duration" : {
"text" : "1 min",
"value" : 40
},
I am using following code to get poly line points
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"points\":\\\"([^\\\"]*)\\\"" options:0 error:NULL];
NSTextCheckingResult *match = [regex firstMatchInString:apiResponse options:0 range:NSMakeRange(0, [apiResponse length])];
NSString *encodedPoints = [apiResponse substringWithRange:[match rangeAtIndex:1]];
return [self decodePolyLine:[encodedPoints mutableCopy]];
but it returns #"" for encodedPoints
is there any problem in regular expression ?
when you got the response in dictionary then do this,
NSMutableArray *pathArray = [NSMutableArray new];
NSArray *routes = [[directionResponse directionResponse] objectForKey:#"routes"];
NSDictionary *route = [routes lastObject];
DLog(#"Array routes :%#",routes);
if (route) {
NSString *overviewPolyline = [[route objectForKey: #"overview_polyline"] objectForKey:#"points"];
pathArray = [self decodePolyLine:overviewPolyline];
}
NSInteger numberOfSteps = pathArray.count;
CLLocationCoordinate2D coordinates[numberOfSteps];
for (NSInteger index = 0; index < numberOfSteps; index++)
{
CLLocation *location = [pathArray objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
coordinates[index] = coordinate;
}
MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps];
I dont think you have to use regex for this, you could use a simple json parser in objetive c and access the poyline and its points, refer :- http://pivotallabs.com/parsing-json-in-objective-c/
I have a JSON like this
{
accountList: [
{
acctId: "",
acctType: ""
},
{
acctId: "",
acctType: ""
}
],
tokenBack: "",
userId: "",
verificationCode: ""
}
and i want accountList array from that JSON as an array. Any one have solution?
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:_responseData options:NSJSONReadingMutableContainers error:nil];
NSArray *accountList = result[#"accountList"];
How do I extract each address from the NSDictionary I instantiated (below), so I can assign to various NSString objects?
I have the following JSON:
{
"Address":[
{
"$":{
"ID":"0"
},
"Address2":[
"10 Smith RD"
],
"City":[
"Mapleville"
],
"State":[
"NJ"
],
"Zip5":[
"90210"
],
"Zip4":[
"764"
]
},
{
"$":{
"ID":"1"
},
"Address2":[
"32 Hog CT"
],
"City":[
"New York City"
],
"State":[
"NY"
],
"Zip5":[
"90210"
],
"Zip4":[
"1390"
]
}
]
}
cData (below) came from the JSON above.
I did the following to convert to a NSDictionary:
NSDictionary* dictionary2 = [NSJSONSerialization JSONObjectWithData:cData options:NSJSONReadingAllowFragments error:nil];
once I did a:
NSLog(#"%#", dictionary2);
output from NSLog:
{
Address = (
{
"$" = {
ID = 0;
};
Address2 = (
"10 Smith RD"
);
City = (
"Mapleville"
);
State = (
NJ
);
Zip4 = (
7642
);
Zip5 = (
90210
);
},
{
"$" = {
ID = 1;
};
Address2 = (
"32 Hog CT"
);
City = (
"New York City"
);
State = (
NY
);
Zip4 = (
1390
);
Zip5 = (
90210
);
}
);
}
Just follow the structure.
NSDictionary* dictionary2 = [NSJSONSerialization ...
NSArray *addresses = dictionary2[#"Address"];
for (NSDictionary *addressData in addresses) {
NSString *address2 = addressData[#"Address2"];
NSString *city = addressData[#"City"];
// and the rest as needed
}