地圖與定位(七)高德定位服務

前言

iOS系統不允許第三方定位,定位功能是對iOS系統定位的二次封裝。通過封裝,可將原始定位點無偏差的顯示在高德地圖上。目前,有兩種獲取當前位置信息的方法:

  • 使用地圖SDK中的定位功能。本文以2D地圖SDK爲例做相關介紹
  • 使用iOS定位SDK,目前提供了獨立的”iOS定位SDK”,無需展示地圖即可獲取用戶位置信息,我們會在以後介紹。

1. 地圖定位

1.1 開啓定位

需在info.plist添加NSLocationWhenInUseUsageDescription或NSLocationAlwaysUsageDescription字段

  • NSLocationWhenInUseUsageDescription表示應用在前臺的時候可以搜到更新的位置信息。
  • NSLocationAlwaysUsageDescription表示應用在前臺和後臺(suspend或terminated)都可以獲取到更新的位置數據。

只要開啓定位開關(MAMapView的showsUserLocation屬性)就可以開始定位。

示例代碼:

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

@interface ViewController ()<MAMapViewDelegate>
{

    MAMapView *_mapView;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    _mapView = [[MAMapView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds))];
    _mapView.delegate = self;

    [self.view addSubview:_mapView];

    // 地圖SDK定位服務
    _mapView.showsUserLocation = YES; //YES 爲打開定位,NO爲關閉定位
    [_mapView setUserTrackingMode: MAUserTrackingModeFollow animated:YES]; //地圖跟着位置移動

    [_mapView setZoomLevel:16.1 animated:YES];

}

#pragma mark - MAMapViewDelegate
-(void)mapView:(MAMapView *)mapView didUpdateUserLocation:(MAUserLocation *)userLocation updatingLocation:(BOOL)updatingLocation
{

    if(updatingLocation)
    {
        //取出當前位置的座標
        NSLog(@"latitude : %f,longitude: %f",userLocation.coordinate.latitude,userLocation.coordinate.longitude);
    }
    // 該方法會頻繁調用多次,但是不能通過關閉定位的方法來解決
//    _mapView.showsUserLocation = NO;
}

1.2 設置定位圖層

將 MAMapView 添加到 Subview 中,開啓定位後,會在地圖上顯示定位圖層。高德地圖 iOS SDK 支持自定義定位圖層的樣式。

通過setUserTrackingMode:可改變定位圖層的顯示模式:定位圖層有3種顯示模式,分別爲:

  • MAUserTrackingModeNone:僅在地圖上顯示,不跟隨用戶位置。
  • MAUserTrackingModeFollow:跟隨用戶位置移動,並將定位點設置成地圖中心點。
  • MAUserTrackingModeFollowWithHeading:跟隨用戶的位置和角度移動。

1.3 自定義定位圖層

定位圖層由定位點處的標註(MAUserLocation)和精度圈(MACircle)組成。通過- (void)mapView:(MAMapView )mapView didAddAnnotationViews:(NSArray )views方法自定義定位標註和精度圈的樣式。

示例代碼:

// 添加用戶大頭針
- (void)mapView:(MAMapView *)mapView didAddAnnotationViews:(NSArray *)views
{
    MAAnnotationView *view = views[0];

    // 放到該方法中用以保證userlocation的annotationView已經添加到地圖上了。
    if ([view.annotation isKindOfClass:[MAUserLocation class]])
    {
        MAUserLocationRepresentation *pre = [[MAUserLocationRepresentation alloc] init];
        pre.fillColor = [UIColor colorWithRed:0.9 green:0.1 blue:0.1 alpha:0.3];
        pre.strokeColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.9 alpha:1.0];
        pre.image = [UIImage imageNamed:@"category_3"];
        pre.lineWidth = 3;
        pre.lineDashPattern = @[@6, @3];

        [_mapView updateUserLocationRepresentation:pre];

        view.calloutOffset = CGPointMake(0, 0);
    }
}

1.4 開啓後臺定位

高德地圖iOS SDK V2.5.0版本提供後臺持續定位的能力,即便你的app退到後臺,且位置不變動時,也不會被系統掛起,可持久記錄位置信息。該功能適用於記軌跡錄或者出行類App司機端。

注意:後臺定位必須將info.plist的字段改成NSLocationAlwaysUsageDescription字段。

只需要您的做以下幾步操作:

  • 添加代碼。
_mapView.pausesLocationUpdatesAutomatically = NO;
_mapView.allowsBackgroundLocationUpdates = YES;//iOS9以上系統必須配置
  • 工程配置。
    1. 左側目錄中選中工程名,開啓 TARGETS->Capabilities->Background Modes
    2. 在 Background Modes中勾選 Location updates,如下圖所示:
      這裏寫圖片描述

2. 高德定位SDK

高德 iOS 定位 SDK 提供了不依賴於地圖定位的定位功能,開發者可以無地圖顯示的場景中便捷地爲應用程序添加定位功能。 iOS定位SDK提供了單次定位、連續定位、逆地理信息、地理圍欄等功能。

2.1 SDK的集成

第一步:下載開發包並解壓。
從中下載定位包,解壓後得到 AMapLocationKit.framework 。
第二步:引入定位包。
在 TARGETS-Build Phases–Link Binary With Libraries 點擊“+”,彈出添加列表後,點擊“Add Other…”,添加 AMapLocationKit.framework到工程中;
這裏寫圖片描述
第三步:引入系統庫文件。
在 TARGETS-General-Linked Frameworks and Libraries 中點擊“+”,彈出添加列表後添加如下系統庫: CoreTelephony.framework, SystemConfiguration.framework, CoreLocation.framework, libz.tbd(Xcode7之前,是libz.dylib)。

第四步:環境配置
(1)配置 Other Link Flag。
在 TARGETS-Build Settings-Other Linker Flags 中添加如下內容: -ObjC;
(2)配置Architectures。
在 TARGETS-Build Settings-Architectures 點擊出選擇框,將值修改爲 $(ARCHS_STANDARD)。
這裏寫圖片描述
第五步:申請應用,獲取註冊appkey
在使用定位SDK時,需要對應用做Key機制驗證,如果不添加Key,定位功能將不能使用: [AMapLocationServices sharedServices].apiKey = @”您的key”;

注意:

  • 需要在info.plist中追加 NSLocationWhenInUseUsageDescription 或NSLocationAlwaysUsageDescription 字段,以申請定位權限。
  • iOS9爲了增強數據訪問安全,將所有的http請求都改爲了https,爲了能夠在iOS9中正常使用地圖SDK,請在”Info.plist”中進行如下配置,否則影響SDK的使用。

2.2 持續定位

iOS定位SDK提供的持續定位功能獲取定位數據(地圖SDK可以將獲取的數據進行展示),與CLLocationManager的使用方法類似。實現持續定位的步驟如下:

  • 初始化AMapLocationManager對象,設置代理。
  • 開啓持續定位,調用AMapLocationManager提供的startUpdatingLocation方法實現。停止持續定位調用AMapLocationManager提供的stopUpdatingLocation方法實現。
  • 接收位置更新,實現AMapLocationManagerDelegate代理的amapLocationManager:didUpdateLocation: 方法,處理位置更新。

示例代碼:

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

@interface ViewController ()<AMapLocationManagerDelegate>
{

    AMapLocationManager *_manager;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [AMapLocationServices sharedServices].apiKey = @"88d606ae8da9c5b8c01e03367526272a";

    // 初始化定位管家並設置代理
    _manager = [[AMapLocationManager alloc] init];
    _manager.delegate = self;

    // 開始持續定位
    [_manager startUpdatingLocation];

    // 停止定位
//    [_manager stopUpdatingLocation];


}

#pragma mark - AMapLocationManagerDelegate
- (void)amapLocationManager:(AMapLocationManager *)manager didUpdateLocation:(CLLocation *)location
{
    NSLog(@"location:{lat:%f; lon:%f; accuracy:%f}", location.coordinate.latitude, location.coordinate.longitude, location.horizontalAccuracy);
}

@end

2.3 單次定位

iOS定位SDK提供的單次定位方法基於蘋果定位核心,蘋果定位核心會在設備移動時連續返回定位結果,高德在此基礎上封裝了單次定位並適配了iOS 6到iOS 9系統。當設備可以正常聯網時,還可以返回該定位點的位置信息(包括:省、市、區/縣以及詳細地址)。 單次定位區別於連續定位,無需設置代理和實現代理方法,與連續定位一樣需要引入AMapLocationKit.h頭文件。

  • 初始化定位管家。
  • 設置期望定位精度。
  • 請求定位並拿到結果,調用AMapLocationManager的requestLocationWithReGeocode:completionBlock: 方法,請求一次定位。

示例代碼:

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

@interface ViewController ()<AMapLocationManagerDelegate>
{
    AMapLocationManager *_manager;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [AMapLocationServices sharedServices].apiKey = @"88d606ae8da9c5b8c01e03367526272a";

    // 初始化定位管家並設置代理
    _manager = [[AMapLocationManager alloc] init];


    // 單次定位
    // 帶逆地理信息的一次定位(返回座標和地址信息)
    [_manager setDesiredAccuracy:kCLLocationAccuracyHundredMeters];// 設置定位精度
    // 定位超時時間,最低2s,
    _manager.locationTimeout = 30;
    // 逆地理請求超時時間,最低2s,
    _manager.reGeocodeTimeout = 30;
    // 高精度:kCLLocationAccuracyBest,精度很高的一次定位,偏差在10米以內,耗時在10s左右。

    // 帶逆地理(返回座標和地址信息)。
    // 獲取單次定位信息,第一個參數設置爲NO,則不會返回地址信息。
    [_manager requestLocationWithReGeocode:NO completionBlock:^(CLLocation *location, AMapLocationReGeocode *regeocode, NSError *error) {

        if (error) {
            NSLog(@"locError:{%ld - %@};", (long)error.code, error.localizedDescription);
            return;
        }
        NSLog(@"location:%@", location);
        if (regeocode) {
            NSLog(@"reGeocode:%@", regeocode);
        }
    }];
}

2.4 後臺定位

iOS定位SDK提供後臺持續定位的能力,可持久記錄位置信息,適用於記軌跡錄。需要引入AMapLocationKit.h頭文件。

  • 更改info.plist

    將info.plist的字段改成NSLocationAlwaysUsageDescription字段。
    
  • 配置後臺定位

    左側目錄中選中工程名,開啓 TARGETS->Capabilities->Background Modes
    在 Background Modes中勾選 Location updates,如下圖所示:
    

    這裏寫圖片描述

示例代碼:

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

@interface ViewController ()<AMapLocationManagerDelegate>
{
    AMapLocationManager *_manager;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [AMapLocationServices sharedServices].apiKey = @"88d606ae8da9c5b8c01e03367526272a";

    // 初始化定位管家並設置代理
    _manager = [[AMapLocationManager alloc] init];
    _manager.delegate = self;

    // 後臺定位
    //設置允許後臺定位參數,保持不會被系統掛起
    [_manager setPausesLocationUpdatesAutomatically:NO];

    [_manager setAllowsBackgroundLocationUpdates:YES];//iOS9(含)以上系統需設置
    // 開始持續定位
    [_manager startUpdatingLocation];

}

#pragma mark - AMapLocationManagerDelegate
- (void)amapLocationManager:(AMapLocationManager *)manager didUpdateLocation:(CLLocation *)location
{
    NSLog(@"location:{lat:%f; lon:%f; accuracy:%f}", location.coordinate.latitude, location.coordinate.longitude, location.horizontalAccuracy);
}

2.5 定位輔助功能

定位SDK爲我們提供了一些輔助功能,主要有一下兩種:

  • 區域判斷:判斷目標經緯度是否在大陸及港、澳地區,方便開發者按需切換國內/海外功能,目前支持判斷目標經緯度是否在大陸及港、澳地區,方便開發者按需切換區域功能。
  • 地理圍欄:以一個圓形的地理邊界作爲虛擬圍欄,當手機進入、離開該區域時,手機可以接收自動通知。

示例代碼:

#import "ViewController.h"
#import <AMapLocationKit/AMapLocationKit.h>
#import <MAMapKit/MAMapKit.h>

@interface ViewController ()<AMapLocationManagerDelegate>
{
    MAMapView *_mapView;
    AMapLocationManager *_manager;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [AMapLocationServices sharedServices].apiKey = @"88d606ae8da9c5b8c01e03367526272a";

    // 初始化定位管家並設置代理
    _manager = [[AMapLocationManager alloc] init];
    _manager.delegate = self;

    // 輔助功能
    // 區域判斷
    //設置一個目標經緯度
    CLLocationCoordinate2D coodinate = CLLocationCoordinate2DMake(39.948691, 116.492479);
    //返回是否在大陸及港、澳地區
    BOOL flag= AMapLocationDataAvailableForCoordinate(coodinate);
    NSLog(@"%d",flag);

    // 地理圍欄
    AMapLocationCircleRegion *cirRegion200 = [[AMapLocationCircleRegion alloc] initWithCenter:CLLocationCoordinate2DMake(40, 119) radius:200.0 identifier:@"circleRegion200"];

    AMapLocationCircleRegion *cirRegion300 = [[AMapLocationCircleRegion alloc] initWithCenter:CLLocationCoordinate2DMake(40, 119) radius:300.0 identifier:@"circleRegion300"];

    //添加地理圍欄
    [_manager startMonitoringForRegion:cirRegion200];
    [_manager startMonitoringForRegion:cirRegion300];


    // 初始化地圖
    _mapView = [[MAMapView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:_mapView];

    //添加Overlay
    MACircle *circle200 = [MACircle circleWithCenterCoordinate:CLLocationCoordinate2DMake(40, 119) radius:200.0];
    MACircle *circle300 = [MACircle circleWithCenterCoordinate:CLLocationCoordinate2DMake(40, 119) radius:300.0];
    [_mapView addOverlay:circle200];
    [_mapView addOverlay:circle300];

    [_mapView setVisibleMapRect:circle300.boundingMapRect];
}

- (void)amapLocationManager:(AMapLocationManager *)manager didEnterRegion:(AMapLocationRegion *)region {
    NSLog(@"進入圍欄:%@", region);
}

- (void)amapLocationManager:(AMapLocationManager *)manager didExitRegion:(AMapLocationRegion *)region {
    NSLog(@"走出圍欄:%@", region);
}

@end
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章