緯度と経度から現在地名を探したいのですが、
これが私が試したコードスニペットですが、placemark
、placemark.ISOcountryCode
およびplacemark.country
を除くすべての場所でログにnull値が表示されます
placemark.locality
とplacemark.subLocality
の値が必要ですが、null値が表示されます。
- (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);
}
よろしくお願いします。
編集:
- (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;
}
}
}];
}
住所の解決に使用しているスニペットをお届けします。コードを理解するために必要な場所にもコメントを含めています。その上、あなたが何かを理解することができなくなった場合は、スニペットからどんな質問でもしてください。
didUpdateToLocation
メソッドに次のスニペットを書き込みます
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;
}
StrAddがジオロケーションを使用して住所を返す場所。
プログラミングをお楽しみください!!
完了ブロックのあるメソッド:
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);
}
}];
}
これはそれを使用する方法です:
CLLocation* eventLocation = [[CLLocation alloc] initWithLatitude:_latitude longitude:_longitude];
[self getAddressFromLocation:eventLocation complationBlock:^(NSString * address) {
if(address) {
_address = address;
}
}];
私はSwiftにNiruのソリューションを実装しました。
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!)"
}
}
これを試して
[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);
}
} ];
Swift 4.1およびXcode 9.4.1の場合、これは私の解決策の1つです。ここではgeocode APIを使用して完全なアドレスを取得しています。このAPIを使用すると、村の名前も取得します。
私はreverseGeocodeLocationを使用していますが、村の住所の詳細や村の名前を取得していません。都市名でのみ取得しています。これは最高のソリューションの1つです。
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
}
}
}
}
}
}
}
}
}
このようにこの関数を呼び出す
self.getAddressForLatLng(latitude: "\(self.lat!)", longitude: "\(self.lng!)")
取得しようとしている場所がこのリストに含まれている場合は、コードに問題があります。
http://developer.Apple.com/library/ios/#technotes/tn2289/_index.html#//Apple_ref/doc/uid/DTS40011305
それ以外の場合、CLGeoCoderには他の国へのアドレスがありません。
私は同じ問題に直面したので、これを使用して住所を取得しました。本当に正確な住所を提供します。
http://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&sensor=true_or_false
まず、didUpdateToLocationで場所をフィルタリングして、ジオコーディングにキャッシュされた場所や間違った場所を使用しないようにします。
NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
if (abs(locationAge) > 5.0) return;
if (newLocation.horizontalAccuracy < 0) return;
また、reverseGeoCodingメソッドをdidUpdateToLocationから遠ざけるようにしてください。
Swift 5
import CoreLocation
func printAddress() {
if let lat = Double(30.710489), lat != 0.0, let long = Double(76.852386), lng != 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"
}
}
})
}
使用できる場所のlatitude
、longitude
の値を取得したら、 CLGeocoder を使用できます tutorial が役立つ場合があります。
このAPIを使用してデータを取得し、緯度と経度の値を渡します。