Reputation: 6490
I want to find current location name from latitude and longitude,
Here is my code snippet I tried but my log shows null value in all the places except in placemark
, placemark.ISOcountryCode
and placemark.country
I want value of placemark.locality
and placemark.subLocality
but it is showing null values.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// this creates the CCLocationManager that will find your current location
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
[locationManager startUpdatingLocation];
}
// this delegate is called when the app successfully finds your current location
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:locationManager.location
completionHandler:^(NSArray *placemarks, NSError *error) {
NSLog(@"reverseGeocodeLocation:completionHandler: Completion Handler called!");
if (error){
NSLog(@"Geocode failed with error: %@", error);
return;
}
NSLog(@"placemarks=%@",[placemarks objectAtIndex:0]);
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSLog(@"placemark.ISOcountryCode =%@",placemark.ISOcountryCode);
NSLog(@"placemark.country =%@",placemark.country);
NSLog(@"placemark.postalCode =%@",placemark.postalCode);
NSLog(@"placemark.administrativeArea =%@",placemark.administrativeArea);
NSLog(@"placemark.locality =%@",placemark.locality);
NSLog(@"placemark.subLocality =%@",placemark.subLocality);
NSLog(@"placemark.subThoroughfare =%@",placemark.subThoroughfare);
}];
}
// this delegate method is called if an error occurs in locating your current location
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(@"locationManager:%@ didFailWithError:%@", manager, error);
}
Thanks In Advance.
EDIT:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
CLLocation *currentLocation = newLocation;
if (currentLocation != nil)
NSLog(@"longitude = %.8f\nlatitude = %.8f", currentLocation.coordinate.longitude,currentLocation.coordinate.latitude);
// stop updating location in order to save battery power
[locationManager stopUpdatingLocation];
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error)
{
NSLog(@"Found placemarks: %@, error: %@", placemarks, error);
if (error == nil && [placemarks count] > 0)
{
CLPlacemark *placemark = [placemarks lastObject];
// strAdd -> take bydefault value nil
NSString *strAdd = nil;
if ([placemark.subThoroughfare length] != 0)
strAdd = placemark.subThoroughfare;
if ([placemark.thoroughfare length] != 0)
{
// strAdd -> store value of current location
if ([strAdd length] != 0)
strAdd = [NSString stringWithFormat:@"%@, %@",strAdd,[placemark thoroughfare]];
else
{
// strAdd -> store only this value,which is not null
strAdd = placemark.thoroughfare;
}
}
if ([placemark.postalCode length] != 0)
{
if ([strAdd length] != 0)
strAdd = [NSString stringWithFormat:@"%@, %@",strAdd,[placemark postalCode]];
else
strAdd = placemark.postalCode;
}
if ([placemark.locality length] != 0)
{
if ([strAdd length] != 0)
strAdd = [NSString stringWithFormat:@"%@, %@",strAdd,[placemark locality]];
else
strAdd = placemark.locality;
}
if ([placemark.administrativeArea length] != 0)
{
if ([strAdd length] != 0)
strAdd = [NSString stringWithFormat:@"%@, %@",strAdd,[placemark administrativeArea]];
else
strAdd = placemark.administrativeArea;
}
if ([placemark.country length] != 0)
{
if ([strAdd length] != 0)
strAdd = [NSString stringWithFormat:@"%@, %@",strAdd,[placemark country]];
else
strAdd = placemark.country;
}
}
}];
}
Upvotes: 18
Views: 44681
Reputation: 27
Here's how to get the address from Location Coordinate (lat,long).
You can get the address info such like city, country, postcode etc. from LocationCoordinates with this code
func getReverSerGeoLocation(location : CLLocation) {
print("getting Address from Location cordinate")
CLGeocoder().reverseGeocodeLocation(location) {
placemarks , error in
if error == nil && placemarks!.count > 0 {
guard let placemark = placemarks?.last else {
return
}
print(placemark.thoroughfare)
print(placemark.subThoroughfare)
print("postalCode :-",placemark.postalCode)
print("City :-",placemark.locality)
print("subLocality :-",placemark.subLocality)
print("subAdministrativeArea :-",placemark.subAdministrativeArea)
print("Country :-",placemark.country)
}
}
}
Just call above method by passing latitude longitude as argument such like below
getReverSerGeoLocation(location: CLLocation(latitude: 21.0225, longitude: 72.5714))
Hope this helps!
Upvotes: 0
Reputation: 10329
Swift 5
import CoreLocation
func printAddress() {
if let lat = Double(30.710489), lat != 0.0, let long = Double(76.852386), long != 0.0 {
// Create Location
let location = CLLocation(latitude: lat, longitude: long)
// Geocode Location
CLGeocoder().reverseGeocodeLocation(location) { (placemarks, error) in
// Process Response
self.processResponse(withPlacemarks: placemarks, error: error)
}
}
}
private func processResponse(withPlacemarks placemarks: [CLPlacemark]?, error: Error?) {
var address = ""
if let error = error {
address = "Unable to Reverse Geocode Location (\(error))"
} else {
if let placemarks = placemarks, let placemark = placemarks.first {
address = placemark.compactAddress ?? ""
} else {
address = "No address found"
}
}
print(address)
}
extension CLPlacemark {
var compactAddress: String? {
if let name = name {
var result = name
if let street = thoroughfare {
result += ", \(street)"
}
if let city = locality {
result += ", \(city)"
}
if let postalCode = postalCode {
result += ", \(postalCode)"
}
if let country = country {
result += ", \(country)"
}
return result
}
return nil
}
}
// 2nd Way
func updateLocation(lat:Double,long:Double) {
CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: Double(lat), longitude: Double(long)), completionHandler: { (placemarks, error) -> Void in
if error != nil {
return
}
else {
var location = ""
let pm = placemarks![0]
if pm.addressDictionary!["FormattedAddressLines"] != nil {
location = "\n" + (pm.addressDictionary!["FormattedAddressLines"] as! NSArray).componentsJoined(by: ", ")
}else{
location = "\n" + "NO_ADDRESS_FOUND"
}
}
})
}
Upvotes: 0
Reputation: 17932
In Swift 4.1 and Xcode 9.4.1, this is one of my solution. Here i'm using geocode API to get the complete address. With this api i can get the village names also.
I'm using reverseGeocodeLocation but it's not getting village address details or village names, it's getting only near by city names. It's one of the finest solution....
func getAddressForLatLng(latitude: String, longitude: String) { // Call this function
let url = NSURL(string: "https://maps.googleapis.com/maps/api/geocode/json?latlng=\(latitude),\(longitude)")//Here pass your latitude, longitude
print(url!)
let data = NSData(contentsOf: url! as URL)
if data != nil {
let json = try! JSONSerialization.jsonObject(with: data! as Data, options: JSONSerialization.ReadingOptions.allowFragments) as! NSDictionary
print(json)
let status = json["status"] as! String
if status == "OK" {
if let result = json["results"] as? NSArray {
if result.count > 0 {
if let addresss:NSDictionary = result[0] as? NSDictionary {
if let address = addresss["address_components"] as? NSArray {
var newaddress = ""
var number = ""
var street = ""
var city = ""
var state = ""
var zip = ""
var country = ""
if(address.count > 1) {
number = (address.object(at: 0) as! NSDictionary)["short_name"] as! String
}
if(address.count > 2) {
street = (address.object(at: 1) as! NSDictionary)["short_name"] as! String
}
if(address.count > 3) {
city = (address.object(at: 2) as! NSDictionary)["short_name"] as! String
}
if(address.count > 4) {
state = (address.object(at: 4) as! NSDictionary)["short_name"] as! String
}
if(address.count > 6) {
zip = (address.object(at: 6) as! NSDictionary)["short_name"] as! String
}
newaddress = "\(number) \(street), \(city), \(state) \(zip)"
print(newaddress)
// OR
//This is second type to fetch pincode, country, state like this type of data
for i in 0..<address.count {
print(((address.object(at: i) as! NSDictionary)["types"] as! Array)[0])
if ((address.object(at: i) as! NSDictionary)["types"] as! Array)[0] == "postal_code" {
zip = (address.object(at: i) as! NSDictionary)["short_name"] as! String
}
if ((address.object(at: i) as! NSDictionary)["types"] as! Array)[0] == "country" {
country = (address.object(at: i) as! NSDictionary)["long_name"] as! String
}
if ((address.object(at: i) as! NSDictionary)["types"] as! Array)[0] == "administrative_area_level_1" {
state = (address.object(at: i) as! NSDictionary)["long_name"] as! String
}
if ((address.object(at: i) as! NSDictionary)["types"] as! Array)[0] == "administrative_area_level_2" {
district = (address.object(at: i) as! NSDictionary)["long_name"] as! String
}
}
}
}
}
}
}
}
}
Call this function like this
self.getAddressForLatLng(latitude: "\(self.lat!)", longitude: "\(self.lng!)")
Upvotes: 0
Reputation: 720
I implemented Niru's solution in Swift 3, posting here should anybody need it:
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(self.location!) { (placemarksArray, error) in
if (placemarksArray?.count)! > 0 {
let placemark = placemarksArray?.first
let number = placemark!.subThoroughfare
let bairro = placemark!.subLocality
let street = placemark!.thoroughfare
self.addressLabel.text = "\(street!), \(number!) - \(bairro!)"
}
}
Upvotes: 8
Reputation: 1287
Try this
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
//..NSLog(@"Found placemarks: %@, error: %@", placemarks, error);
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
lblgetaddrees.text = [NSString stringWithFormat:@"%@,%@,%@,%@,%@,%@",
placemark.subThoroughfare, placemark.thoroughfare,
placemark.postalCode, placemark.locality,
placemark.administrativeArea,
placemark.country];
} else {
//..NSLog(@"%@", error.debugDescription);
}
} ];
Upvotes: 0
Reputation: 927
Method with completion block:
typedef void(^addressCompletion)(NSString *);
-(void)getAddressFromLocation:(CLLocation *)location complationBlock:(addressCompletion)completionBlock
{
__block CLPlacemark* placemark;
__block NSString *address = nil;
CLGeocoder* geocoder = [CLGeocoder new];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error)
{
if (error == nil && [placemarks count] > 0)
{
placemark = [placemarks lastObject];
address = [NSString stringWithFormat:@"%@, %@ %@", placemark.name, placemark.postalCode, placemark.locality];
completionBlock(address);
}
}];
}
This is how to use it:
CLLocation* eventLocation = [[CLLocation alloc] initWithLatitude:_latitude longitude:_longitude];
[self getAddressFromLocation:eventLocation complationBlock:^(NSString * address) {
if(address) {
_address = address;
}
}];
Upvotes: 11
Reputation: 170
Use google api for reverse geotagging :
URL : http://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&sensor=true_or_false
From : https://developers.google.com/maps/documentation/geocoding/
Upvotes: 2
Reputation: 4733
I'm giving you snippet which I'm using for resolving address. I'm including comment also at neccessary place to understand the code for you. Besides that feel free to ask any question from snippet if you get fail to understand anything.
Write following snippet in didUpdateToLocation
method
NSLog(@"didUpdateToLocation: %@", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil)
NSLog(@"longitude = %.8f\nlatitude = %.8f", currentLocation.coordinate.longitude,currentLocation.coordinate.latitude);
// stop updating location in order to save battery power
[locationManager stopUpdatingLocation];
// Reverse Geocoding
NSLog(@"Resolving the Address");
// “reverseGeocodeLocation” method to translate the locate data into a human-readable address.
// The reason for using "completionHandler" ----
// Instead of using delegate to provide feedback, the CLGeocoder uses “block” to deal with the response. By using block, you do not need to write a separate method. Just provide the code inline to execute after the geocoding call completes.
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error)
{
NSLog(@"Found placemarks: %@, error: %@", placemarks, error);
if (error == nil && [placemarks count] > 0)
{
placemark = [placemarks lastObject];
// strAdd -> take bydefault value nil
NSString *strAdd = nil;
if ([placemark.subThoroughfare length] != 0)
strAdd = placemark.subThoroughfare;
if ([placemark.thoroughfare length] != 0)
{
// strAdd -> store value of current location
if ([strAdd length] != 0)
strAdd = [NSString stringWithFormat:@"%@, %@",strAdd,[placemark thoroughfare]];
else
{
// strAdd -> store only this value,which is not null
strAdd = placemark.thoroughfare;
}
}
if ([placemark.postalCode length] != 0)
{
if ([strAdd length] != 0)
strAdd = [NSString stringWithFormat:@"%@, %@",strAdd,[placemark postalCode]];
else
strAdd = placemark.postalCode;
}
if ([placemark.locality length] != 0)
{
if ([strAdd length] != 0)
strAdd = [NSString stringWithFormat:@"%@, %@",strAdd,[placemark locality]];
else
strAdd = placemark.locality;
}
if ([placemark.administrativeArea length] != 0)
{
if ([strAdd length] != 0)
strAdd = [NSString stringWithFormat:@"%@, %@",strAdd,[placemark administrativeArea]];
else
strAdd = placemark.administrativeArea;
}
if ([placemark.country length] != 0)
{
if ([strAdd length] != 0)
strAdd = [NSString stringWithFormat:@"%@, %@",strAdd,[placemark country]];
else
strAdd = placemark.country;
}
Where strAdd will return address using geolocation..
Enjoy Programming !!
Upvotes: 14
Reputation: 1242
Once you have latitude
, longitude
values of a location you can use CLGeocoder
here is a tutorial which might help you.
Upvotes: 0
Reputation: 4817
First of all, filter locations in didUpdateToLocation to prevent use cached or wrong locations for geocoding
NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
if (abs(locationAge) > 5.0) return;
if (newLocation.horizontalAccuracy < 0) return;
Also, try to move the reverseGeoCoding method away from didUpdateToLocation
Upvotes: 0
Reputation: 2337
If the location you are trying to get is listed in this list then there is something wrong in your code..
http://developer.apple.com/library/ios/#technotes/tn2289/_index.html#//apple_ref/doc/uid/DTS40011305
otherwise CLGeoCoder doesnt have addresses to other countries.
I faced the same problem so i used this to get the address.. Gives a really accurate address.
http://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&sensor=true_or_false
Upvotes: 0