在IOS開(kāi)發(fā)中,最常見(jiàn)的功能之一就是地圖定位功能,不單單是百度地圖,高德地圖等專業(yè)的地圖導(dǎo)航軟件,還有美團(tuán),咕咚等一些美食購(gòu)物類和運(yùn)動(dòng)類也需要這樣的功能,所以學(xué)會(huì)這項(xiàng)技能是一名IOS開(kāi)發(fā)工程師必須的.
分享一些比較基礎(chǔ)的關(guān)于定位方面的小知識(shí).
關(guān)于定位有兩個(gè)框架
1.CoreLocation ---->用于地理定位
2.Map Kit ---->用于地圖展示
兩個(gè)熱詞:
LBS: location based service
SLM: social local mobile
使用CoreLocation定位
首先在之前需要導(dǎo)入corelocation框架,然后在頭文件導(dǎo)入corelocation.h頭文件.
注意:coordinate是坐標(biāo),latitude是緯度,longitude是經(jīng)度.
- (void)viewDidLoad {
[super viewDidLoad];
// 1.創(chuàng)建位置管理者
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
self.locationManager = locationManager;
// 在iO8之前,只要導(dǎo)入CoreLocation 會(huì)自動(dòng)申請(qǐng)權(quán)限
// 在iOS8之后需要程序員手寫(xiě)
// 2.請(qǐng)求用戶授權(quán) 必須要配置info.plist文件
//在info里面配置NSLocationAlwaysUsageDescription或者
//NSLocationWhenInUseUsageDescription
// 請(qǐng)求app始終授權(quán) 無(wú)論程序在前臺(tái)還是在后臺(tái)運(yùn)行 都可以使用定位
// [locationManager requestAlwaysAuthorization];
// 請(qǐng)求app在使用期間授權(quán) 在前臺(tái)使用時(shí)才可以使用定位
[locationManager requestWhenInUseAuthorization];
if ([UIDevice currentDevice].systemVersion.floatValue >= 9.0) {
// 臨時(shí)開(kāi)啟后臺(tái)定位 配置info.plist文件 不配置直接崩潰
locationManager.allowsBackgroundLocationUpdates = YES;
}
// 3.設(shè)置屬性(兩個(gè)屬性是為了讓程序可以持續(xù)的進(jìn)行定位)
// // 距離篩選 單位:米 當(dāng)用戶移動(dòng)100.5米后調(diào)用定位方法
// locationManager.distanceFilter = 100.5;
// // 期望精度 單位:米 系統(tǒng)默認(rèn)將100米范圍內(nèi)作為一個(gè)位置
// locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// 4.設(shè)置代理
locationManager.delegate = self;
// 5.開(kāi)啟定位
[locationManager startUpdatingLocation];
// 開(kāi)始更新移動(dòng)方向
// [locationManager startUpdatingHeading];
//代理方法,一旦開(kāi)啟定位,會(huì)自動(dòng)調(diào)用這個(gè)代理方法
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
// 獲取數(shù)據(jù)
// NSLog(@"%@",locations);
// 停止定位 省電
// [manager stopUpdatingLocation];
}
// 比較位置的距離 比較的是兩點(diǎn)之間的直線距離
- (void)compareDistance
{
// 北京的位置
CLLocation *location = [[CLLocation alloc] initWithLatitude:39 longitude:115];
// 上海的位置
CLLocation *location1 = [[CLLocation alloc] initWithLatitude:30 longitude:120];
// 比較北京到上海的位置(直線距離)
double distance = [location distanceFromLocation:location1];
// 單位:米
NSLog(@"%f",distance / 1000);
}
使用MapKit定位
修改地圖類型 mapView.mapType
地圖實(shí)時(shí)交通狀態(tài) mapView.showsTraffic
設(shè)置用戶跟蹤模式 mapView.userTrackingMode
代理方法,
//顯示在地圖中用戶定位的位置
-(void)mapView:(MKMapView\*)mapView didUpdateUserLocation:(MKUserLocation \*)userLocation
//獲取實(shí)時(shí)地圖變化的區(qū)域變化(中心點(diǎn),區(qū)域跨度)
-(void)mapView:(MKMapView \*)mapView regionDidChangeAnimated:(BOOL)animated
注意:這里需要導(dǎo)入的是MapKit框架和MapKit.h頭文件.
- (void)viewDidLoad {
[super viewDidLoad];
// 修改地圖類型
/*
MKMapTypeStandard 標(biāo)準(zhǔn)(默認(rèn))
MKMapTypeSatellite 衛(wèi)星
MKMapTypeHybrid 混合
MKMapTypeSatelliteFlyover 在中國(guó)暫時(shí)不能使用
MKMapTypeHybridFlyover 在中國(guó)暫時(shí)不能使用
*/
self.mapView.mapType = MKMapTypeStandard;
// 實(shí)時(shí)交通狀況 iOS9新增
self.mapView.showsTraffic = YES;
// 創(chuàng)建位置管理者
self.locationManager = [[CLLocationManager alloc] init];
// 請(qǐng)求用戶授權(quán) 配置info.plist
[self.locationManager requestWhenInUseAuthorization];
// 設(shè)置用戶的跟蹤模式
/*
MKUserTrackingModeFollow 跟蹤用戶的位置 MKUserTrackingModeFollowWithHeading 跟蹤用戶的位置和方向
*/
self.mapView.userTrackingMode = MKUserTrackingModeFollow;
// 設(shè)置代理
self.mapView.delegate = self;
}
// 跟蹤到用戶位置時(shí)調(diào)用
// mapView:地圖
// userLocation:用戶位置的大頭針模型
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
// 1.反地理編碼
// 1.1創(chuàng)建地理編碼對(duì)象
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
// 1.2反地理編碼
[geocoder reverseGeocodeLocation:userLocation.location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
// 1.3防錯(cuò)處理
if (error) {
NSLog(@"%@",error);
return ;
}
// 1.4獲取地標(biāo)
CLPlacemark *placemark = [placemarks firstObject];
// 2.給標(biāo)題和子標(biāo)題賦值
userLocation.title = placemark.locality;
userLocation.subtitle = placemark.name;
}];
}
// 回到當(dāng)前用戶的位置
- (IBAction)backToCurrentLocation
{
// 獲取當(dāng)前的跨度
MKCoordinateSpan span = MKCoordinateSpanMake(0.024967, 0.015407);
// 設(shè)置回到用戶剛開(kāi)始的區(qū)域 region(結(jié)構(gòu)體) --1.中心點(diǎn)經(jīng)緯度(結(jié)構(gòu)體)--> 經(jīng)度和緯度 2.經(jīng)緯度跨度(結(jié)構(gòu)體)-->經(jīng)度跨度和緯度跨度
// 設(shè)置區(qū)域并使用動(dòng)畫(huà)
[self.mapView setRegion:MKCoordinateRegionMake(self.mapView.userLocation.location.coordinate, span) animated:YES];
}
- (IBAction)biggerMap
{
// 修改經(jīng)緯度跨度
CGFloat latitudeDelta = self.mapView.region.span.latitudeDelta * 0.5;
CGFloat longitudeDelta = self.mapView.region.span.longitudeDelta * 0.5;
MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
// 確定放大地圖后的區(qū)域
[self.mapView setRegion:MKCoordinateRegionMake(self.mapView.centerCoordinate, span) animated:YES];
}
- (IBAction)smallerMap
{
// 修改經(jīng)緯度跨度
CGFloat latitudeDelta = self.mapView.region.span.latitudeDelta * 2;
CGFloat longitudeDelta = self.mapView.region.span.longitudeDelta * 2;
MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
[self.mapView setRegion:MKCoordinateRegionMake(self.mapView.centerCoordinate, span) animated:YES];
}
演示
說(shuō)到底,其實(shí)蘋(píng)果官方的框架已經(jīng)做得不錯(cuò)了,該有的功能基本都具備,而且使用起來(lái)不是怎么困難,掌握起來(lái)也非匙嗪颍快.我這里只是分享一些比較基礎(chǔ)的功能,歡迎工程師們賜教.
另外附上地理編碼的小演示.