1. 程式人生 > >iOS程式設計師之高德地圖SDK

iOS程式設計師之高德地圖SDK

高德SDK

最近專案中需要定位客戶位置,要滿足地址搜尋,長按地圖新增,同時大頭針還要能移動的需求,這裡整理下,希望幫助有需要的人

1.新增地圖

    // 地圖
    _mapView = [[MAMapView alloc] initWithFrame:CGRectMake(0, lineView.bottom, SCREEN_WIDTH, SCREEN_HEIGHT-lineView.bottom-kViewMargin)];
    _mapView.showsCompass = NO; // 隱藏指南針
    _mapView.showsScale = NO; // 隱藏比例尺
    _mapView.delegate = self;
    [_mapView setUserTrackingMode:MAUserTrackingModeFollow animated:YES]; // 追蹤使用者位置
    [self.view addSubview:_mapView];

2.搜尋按鈕點選事件

// 搜尋按鈕事件
- (void)actionSearchAddress:(UIButton *)button
{
    [self.view endEditing:YES]; // 結束編輯回收鍵盤
    [[CustomActivityIndicator sharedActivityIndicator] startSynchAnimating];
    
    [_mapView removeAnnotation:_annotation]; // 移除大頭針
    
    //構造AMapGeocodeSearchRequest物件,address為必選項,city為可選項
    AMapGeocodeSearchRequest *geo = [[AMapGeocodeSearchRequest alloc] init];
    geo.address = _searchContentTF.text;
    
    //發起正向地理編碼
    [_mapSearch AMapGeocodeSearch: geo];
}

3.高德地圖代理方法(3.0以上的高德SDK包含點選,長按等地圖手勢的代理方法)

#pragma mark - MAMapViewDelegate
// 大頭針樣式
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id <MAAnnotation>)annotation
{
    if ([annotation isKindOfClass:[ReGeocodeAnnotation class]])
    {
        static NSString *pointReuseIndentifier = @"SearchAdressAnnotationView";
        MAPinAnnotationView *annotationView = (MAPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndentifier];
        if (annotationView == nil)
        {
            annotationView = [[MAPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndentifier];
        }
        annotationView.canShowCallout= YES;       //設定氣泡可以彈出,預設為NO
        annotationView.animatesDrop = YES;        //設定標註動畫顯示,預設為NO
        annotationView.draggable = YES;        //設定標註可以拖動,預設為NO
        annotationView.pinColor = MAPinAnnotationColorPurple;
        
        // 新增點到數值中,便於改變時移除
//        if (!_annotationsArray) {
//            _annotationsArray = [NSMutableArray array];
//        }
//        [_annotationsArray addObject:annotation];
//        _annotation = annotation;
        
        return annotationView;
    }
    return nil;
}
// 單擊地圖
- (void)mapView:(MAMapView *)mapView didSingleTappedAtCoordinate:(CLLocationCoordinate2D)coordinate
{
    [self.view endEditing:YES];
}
// 拖拽大頭針觸發方法
- (void)mapView:(MAMapView *)mapView annotationView:(MAAnnotationView *)view didChangeDragState:(MAAnnotationViewDragState)newState fromOldState:(MAAnnotationViewDragState)oldState
{
    if (newState == MAAnnotationViewDragStateEnding)
    {
        _isSearchFromDragging = YES;
        
        CLLocationCoordinate2D coordinate = view.annotation.coordinate;
        self.annotation = view.annotation;
        
        [self searchReGeocodeWithCoordinate:coordinate];
    }
}
// 長按觸發方法
- (void)mapView:(MAMapView *)mapView didLongPressedAtCoordinate:(CLLocationCoordinate2D)coordinate
{
    [self.mapView removeAnnotation:_annotation];
    _isSearchFromDragging = NO;
    [self searchReGeocodeWithCoordinate:coordinate];
}

4.長按和移動大頭針時呼叫逆地理編碼方法

// 逆地址編碼搜尋
- (void)searchReGeocodeWithCoordinate:(CLLocationCoordinate2D)coordinate
{
    AMapReGeocodeSearchRequest *regeo = [[AMapReGeocodeSearchRequest alloc] init];
    
    regeo.location = [AMapGeoPoint locationWithLatitude:coordinate.latitude longitude:coordinate.longitude];
    regeo.requireExtension            = YES;
    
    [_mapSearch AMapReGoecodeSearch:regeo];
}

5.高德search的代理方法

#pragma mark - AMapSearchDelegate
//實現正向地理編碼的回撥函式
- (void)onGeocodeSearchDone:(AMapGeocodeSearchRequest *)request response:(AMapGeocodeSearchResponse *)response
{
    if(response.geocodes.count == 0)
    {
        return;
    } else {
        
        // 通過AMapGeocodeSearchResponse物件處理搜尋結果, 只要一個位置
        AMapGeocode *p = response.geocodes[0];
//        NSLog(@"%f,,%f",p.location.latitude, p.location.longitude);
        ReGeocodeAnnotation *pointAnnotation = [[ReGeocodeAnnotation alloc] init];
        pointAnnotation.coordinate = CLLocationCoordinate2DMake(p.location.latitude, p.location.longitude);
        pointAnnotation.title = _searchContentTF.text;
        [_mapView addAnnotation:pointAnnotation];
        
        _searchContentTF.text = pointAnnotation.title;
        // 儲存點
        _annotation = pointAnnotation;
        [self.mapView selectAnnotation:self.annotation animated:YES];

        // 改變地圖的中心點為大頭針的中心點
        MACoordinateRegion theRegion = {{0.0, 0.0 }, { 0.0, 0.0 }};
        theRegion.center = CLLocationCoordinate2DMake(p.location.latitude, p.location.longitude);
        theRegion.span.longitudeDelta = 0.05f;
        theRegion.span.latitudeDelta = 0.05f;
        [_mapView setRegion:theRegion animated:YES];

    }
    
    [[CustomActivityIndicator sharedActivityIndicator] stopSynchAnimating];
}
// 逆地理編碼回撥.
- (void)onReGeocodeSearchDone:(AMapReGeocodeSearchRequest *)request response:(AMapReGeocodeSearchResponse *)response
{
    if (response.regeocode != nil && _isSearchFromDragging == NO)
    {
        CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(request.location.latitude, request.location.longitude);
        ReGeocodeAnnotation *reGeocodeAnnotation = [[ReGeocodeAnnotation alloc] initWithCoordinate:coordinate reGeocode:response.regeocode];
        
        [self.mapView addAnnotation:reGeocodeAnnotation];
        _annotation = reGeocodeAnnotation;
        _searchContentTF.text = reGeocodeAnnotation.title;
        [self.mapView selectAnnotation:reGeocodeAnnotation animated:YES];
    }
    else /* from drag search, update address */
    {
        [self.annotation setAMapReGeocode:response.regeocode];
        _searchContentTF.text = [NSString stringWithFormat:@"%@%@%@%@", response.regeocode.addressComponent.province?: @"", response.regeocode.addressComponent.city ?: @"", response.regeocode.addressComponent.district?: @"", response.regeocode.addressComponent.township?: @""];
        [self.mapView selectAnnotation:self.annotation animated:YES];
    }
}

6.ReGeocodeAnnotation是自定義的類,程式碼如下:

ReGeocodeAnnotation.h

#import <MAMapKit/MAMapKit.h>
#import <AMapSearchKit/AMapCommonObj.h>

@interface ReGeocodeAnnotation : NSObject <MAAnnotation>

- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate reGeocode:(AMapReGeocode *)reGeocode;

@property (nonatomic, readonly, strong) AMapReGeocode *reGeocode;

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;

@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;


- (void)setAMapReGeocode:(AMapReGeocode *)reGerocode;

@end
ReGeocodeAnnotation.m
#import "ReGeocodeAnnotation.h"

@interface ReGeocodeAnnotation ()

@property (nonatomic, readwrite, strong) AMapReGeocode *reGeocode;
@property (nonatomic, readwrite) CLLocationCoordinate2D coordinate;

@end

@implementation ReGeocodeAnnotation
@synthesize reGeocode  = _reGeocode;
@synthesize coordinate = _coordinate;

- (void)setAMapReGeocode:(AMapReGeocode *)reGerocode
{
    self.reGeocode = reGerocode;
    
    [self updateContent];
}

- (void)updateContent
{
    /* 包含 省, 市, 區以及鄉鎮.  */
    self.title = [NSString stringWithFormat:@"%@%@%@%@",
                  self.reGeocode.addressComponent.province?: @"",
                  self.reGeocode.addressComponent.city ?: @"",
                  self.reGeocode.addressComponent.district?: @"",
                  self.reGeocode.addressComponent.township?: @""];

    /* 包含 社群,建築. */
//    self.subtitle = [NSString stringWithFormat:@"%@%@",
//                     self.reGeocode.addressComponent.neighborhood?: @"",
//                     self.reGeocode.addressComponent.building?: @""];
}

#pragma mark - Life Cycle

- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate reGeocode:(AMapReGeocode *)reGeocode
{
    if (self = [super init])
    {
        self.coordinate = coordinate;
        self.reGeocode  = reGeocode;
        [self updateContent];
    }
    
    return self;
}

@end

有時可能會需要修改地圖顯示範圍,方法如下:

- (void)figureMapRegion
{
    if (_allPointArray.count == 1) { // 一個點
        MACoordinateRegion theRegion = {{0.0, 0.0 }, { 0.0, 0.0 }};
        theRegion.center = CLLocationCoordinate2DMake([_allPointArray[0][@"latitude"] doubleValue], [_allPointArray[0][@"longitude"] doubleValue]);
        theRegion.span.longitudeDelta = 0.05f;
        theRegion.span.latitudeDelta = 0.05f;
        [_mapView setRegion:theRegion animated:YES];
    }
    
    if (_allPointArray.count > 1) { // 多個點
        //構造多邊形資料物件
        CLLocationCoordinate2D polylineCoords;
        double maxLat = 0;
        double maxLon = 0;
        double minLat = 0;
        double minLon = 0;
       
        for (int i=0; i<_allPointArray.count; i++) {
            NSDictionary *dic = _allPointArray[i];
            polylineCoords.latitude = [dic[@"latitude"] doubleValue];
            polylineCoords.longitude = [dic[@"longitude"] doubleValue];
            
            if (i==0) {
                maxLat=[dic[@"latitude"] doubleValue];
                minLat=[dic[@"latitude"] doubleValue];
                maxLon=[dic[@"longitude"] doubleValue];
                minLon=[dic[@"longitude"] doubleValue];
            } else {
                if (maxLat<[dic[@"latitude"] doubleValue]) {
                    maxLat=[dic[@"latitude"] doubleValue];
                }
                if (minLat>[dic[@"latitude"] doubleValue]) {
                    minLat=[dic[@"latitude"] doubleValue];
                }
                if (maxLon<[dic[@"longitude"] doubleValue]) {
                    maxLon=[dic[@"longitude"] doubleValue];
                }
                if (minLon>[dic[@"longitude"] doubleValue]) {
                    minLon=[dic[@"longitude"] doubleValue];
                }
            }
        }
        
        // 設定地圖範圍及中心
        [self setMapRegionAndCenterWithMaxLatitude:maxLat minLatitude:minLat maxLongitude:maxLon minLongitude:minLon];
    }
    
}

// 設定地圖的範圍
- (void)setMapRegionAndCenterWithMaxLatitude:(double)maxLat minLatitude:(double)minLat maxLongitude:(double)maxLon minLongitude:(double)minLon
{
    CLLocationCoordinate2D center = CLLocationCoordinate2DMake((maxLat+minLat)/2, (maxLon+minLon)/2);
    MACoordinateSpan span = MACoordinateSpanMake((maxLat-minLat)*1.5, (maxLon-minLon)*1.5);
    MACoordinateRegion regin = MACoordinateRegionMake(center, span);
    [_mapView setRegion:regin animated:YES];
}