iOS專案開發實戰——CoreLocation地理編碼和反地理編碼

乞力馬紮羅的雪CYF發表於2015-09-20

      地理編碼是把某個具體的位置計算為經緯度,反地理編碼正好相反。這個功能在CoreLocation中如何實現呢?

(1)程式碼如下:

#import "ViewController.h"
#import <MapKit/MapKit.h>

@interface ViewController ()<CLLocationManagerDelegate,MKMapViewDelegate>

@property (nonatomic, strong) MKMapView * mapView;
@property (nonatomic, strong) CLLocationManager * locationManager;
@property (nonatomic, strong) UITextField * textField;
@property (nonatomic, strong) NSString * titleString;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

//    116.456011,39.941272
    _mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
    [_mapView setDelegate:self];
    [_mapView setShowsUserLocation:YES];
    [_mapView setMapType:MKMapTypeStandard];
    [self.view addSubview:_mapView];
    
    UILongPressGestureRecognizer * longpressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressed:)];
    [_mapView addGestureRecognizer:longpressGestureRecognizer];
    
    _textField = [[UITextField alloc] init];
    [_textField setTranslatesAutoresizingMaskIntoConstraints:NO];
    [_textField setBackgroundColor:[UIColor whiteColor]];
    [self.view addSubview:_textField];
    
    UIButton * btn = [UIButton buttonWithType:UIButtonTypeCustom];
    [btn setBackgroundColor:[UIColor orangeColor]];
    [btn setTitle:@"查詢" forState:UIControlStateNormal];
    [btn setTranslatesAutoresizingMaskIntoConstraints:NO];
    [btn addTarget:self action:@selector(theBtnPressed:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
    
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[_textField][btn(100)]-20-|"
                                                                     options:0
                                                                     metrics:nil
                                                                        views:NSDictionaryOfVariableBindings(_textField,btn)]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[_textField(30)]-(-30)-[btn(30)]"
                                                                      options:0
                                                                      metrics:nil
                                                                        views:NSDictionaryOfVariableBindings(_textField,btn)]];
    
    //檢測定位功能是否開啟
    if([CLLocationManager locationServicesEnabled]){
        
        if(!_locationManager){
           
            _locationManager = [[CLLocationManager alloc] init];
            
            if([_locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]){
                [_locationManager requestWhenInUseAuthorization];
                [_locationManager requestAlwaysAuthorization];
                
            }

            //設定代理
            [_locationManager setDelegate:self];
            //設定定位精度
            [_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
            //設定距離篩選
            [_locationManager setDistanceFilter:100];
            //開始定位
            [_locationManager startUpdatingLocation];
            //設定開始識別方向
            [_locationManager startUpdatingHeading];
            
        }
        
    }else{
        UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:nil
                                                             message:@"您沒有開啟定位功能"
                                                            delegate:nil
                                                   cancelButtonTitle:@"確定"
                                                   otherButtonTitles:nil, nil];
        [alertView show];
    }
}

//點選按鈕執行此方法
- (void)theBtnPressed:(id)sender {
    [_textField resignFirstResponder];
    if([_textField.text length] == 0){
        
        return;
    }
    [self geocoder:_textField.text];
}

#pragma mark LongPress
- (void)longPressed:(UILongPressGestureRecognizer *)recognizer {
    if(recognizer.state == UIGestureRecognizerStateBegan){
        CGPoint point = [recognizer locationInView:_mapView];
        CLLocationCoordinate2D coordinate2D = [_mapView convertPoint:point toCoordinateFromView:_mapView];
        
        [_mapView removeAnnotations:_mapView.annotations];
        
        CLLocation * location = [[CLLocation alloc] initWithLatitude:coordinate2D.latitude longitude:coordinate2D.longitude];
        
        [self reverseGeocoder:location];
        
//        MKPointAnnotation * pointAnnotation = [[MKPointAnnotation alloc] init];
//        [pointAnnotation setTitle:_titleString];
//        [pointAnnotation setCoordinate:coordinate2D];
//        [_mapView addAnnotation:pointAnnotation];
    }
}

//授權狀態發生改變的時候執行
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
    switch(status){
        case kCLAuthorizationStatusDenied:
        {
            UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:nil
                                                                 message:@"定位功能沒有開啟" delegate:nil
                                                       cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];
            [alertView show];
        }
            break;
        default:
            break;
    }
}

#pragma mark mapViewDelegate 
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
    static NSString * key = @"key";
    MKPinAnnotationView * pinAnnotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:key];
    
    if(pinAnnotationView == nil){
        pinAnnotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:key];
        [pinAnnotationView setCanShowCallout:YES];
    }
    
    if([annotation isKindOfClass:[MKUserLocation class]]){
        [pinAnnotationView setPinColor:MKPinAnnotationColorRed];
        [((MKUserLocation *)annotation) setTitle:_titleString];
    }else{
        [pinAnnotationView setPinColor:MKPinAnnotationColorPurple];
    }
    
    return pinAnnotationView;
}

#pragma mark - CLLocationManangerDelegate
//定位成功以後呼叫
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
    [_locationManager stopUpdatingLocation];
    CLLocation * location = locations.lastObject;
    
    MKCoordinateRegion coordinateRegion = MKCoordinateRegionMake(CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude), MKCoordinateSpanMake(0.1, 0.1));
    
    [_mapView setRegion:[_mapView regionThatFits:coordinateRegion] animated:YES];
    
//    [self reverseGeocoder:location];
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    NSLog(@"error:%@",error);
}


#pragma mark Geocoder
//反地理編碼
- (void)reverseGeocoder:(CLLocation *)currentLocation {
    
    CLGeocoder * geocoder = [[CLGeocoder alloc] init];
    [geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
    
        if(error || placemarks.count == 0){
            NSLog(@"error");
        }else{
            
            CLPlacemark * placemark = placemarks.firstObject;
            
            self.titleString = placemark.name;
            MKPointAnnotation * pointAnnotation = [[MKPointAnnotation alloc] init];
            [pointAnnotation setTitle:placemark.name];
            [pointAnnotation setCoordinate:CLLocationCoordinate2DMake(placemark.location.coordinate.latitude, placemark.location.coordinate.longitude)];
            [_mapView addAnnotation:pointAnnotation];
            
            NSLog(@"placemark:%@",[[placemark addressDictionary] objectForKey:@"City"]);
        }
        
    }];
}

//地理編碼
- (void)geocoder:(NSString *)str {
    CLGeocoder * geocoder = [[CLGeocoder alloc] init];
    [geocoder geocodeAddressString:str completionHandler:^(NSArray *placemarks, NSError *error) {
       
        if(error || placemarks.count == 0){
            NSLog(@"error");
        }else{
            CLPlacemark * placemark = placemarks.firstObject;
            MKCoordinateRegion coordinateRegion = MKCoordinateRegionMake(CLLocationCoordinate2DMake(placemark.location.coordinate.latitude, placemark.location.coordinate.longitude), MKCoordinateSpanMake(0.1, 0.1));
            
            [_mapView setRegion:[_mapView regionThatFits:coordinateRegion] animated:YES];
            
            MKPointAnnotation * pointAnnotation = [[MKPointAnnotation alloc] init];
            [pointAnnotation setTitle:placemark.name];
            [pointAnnotation setCoordinate:CLLocationCoordinate2DMake(placemark.location.coordinate.latitude, placemark.location.coordinate.longitude)];
            [_mapView addAnnotation:pointAnnotation];
        }
        
    }];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

(2)實現效果如下:


(3)通過輸入框的搜尋,也能定位到具體的位置。長按地圖,就能獲得某個位置的詳細地址。應該說非常方便。


github主頁:https://github.com/chenyufeng1991  。歡迎大家訪問!

相關文章