專業術語 1. LBS :Location Based Serviceios
2. SoLoMo :Social Local Mobile(索羅門)git
CLLocation用來表示某個位置的地理信息,好比經緯度、海拔等等數組
@property(readonly, nonatomic) CLLocationCoordinate2D coordinate;經緯度app
@property(readonly, nonatomic) CLLocationDistance altitude;海拔框架
@property(readonly, nonatomic) CLLocationDirection course;路線,航向(取值範圍是0.0° ~ 359.9°,0.0°表明真北方向)函數
@property(readonly, nonatomic) CLLocationSpeed speed;行走速度(單位是m/s)性能
@property(assign, nonatomic) CLLocationDistance distanceFilter;每隔多少米定位一次測試
@property(assign, nonatomic) CLLocationAccuracy desiredAccuracy;定位精確度(越精確就越耗電)atom
CLLocationCoordinate2D是一個用來表示經緯度的結構體,通常用CLLocationCoordinate2DMake函數來建立CLLocationCoordinate2Dspa
typedef struct {
CLLocationDegrees latitude; // 緯度
CLLocationDegrees longitude; // 經度
} CLLocationCoordinate2D;
中國的經緯度範圍
緯度範圍:N 3°51′ ~ N 53°33′
經度範圍:E 73°33′ ~ E 135°05′
中國部分城市的經緯度
用- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location方法能夠計算2個位置之間的距離
1、獲取用戶的位置
一、在應⽤中使用CoreLocation,須要將框架 CoreLocation 加入項⺫標,而且根據須要導入Core Location 頭文件
#import<CoreLocation/CoreLocation.h> //用於地理定位
二、要在應用中使用MapKit,須要將框架MapKit加入項目標,並在所用它的類中導入MapKit頭文件
#import<MapKit/MapKit.h> //用於地圖展現
三、Core Location 尊重用戶隱私,僅在用戶許可時獲取設備的當前位置。在應用「設置」的「隱私」部 分,能夠關閉或開啓定位服務,還能夠禁止或容許特定應用獲取位置信息, 要請求用戶容許使⽤定位服務,應用須要讓CLLocationManager實例開始更新當前位置或將 MKMapView實例的屬性 ShowsUserLocation設置爲YES。若是設備關閉了定位服務,Core Location將提醒用戶在應用「設置」中開啓定位服務;若是Core Location之前未請求⽤戶容許獲取 設備的位置,它將顯示一個提示框,請求⽤戶許可。
//CoreLocation中使用CLLocationManager對象來作用戶定位
self.locationManager = [[CLLocationManager alloc] init]; self.locationManager.delegate = self; [self.locationManager startUpdatingLocation];
//受權狀態 if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) { //申請受權 [self.locationManager requestWhenInUseAuthorization]; }
// kCLAuthorizationStatusNotDetermined = 0//用戶還沒有作出決定是否啓用定位服務
// kCLAuthorizationStatusRestricted//沒有得到用戶受權使用定位服務,可能用戶沒有本身禁止訪問受權
// kCLAuthorizationStatusDenied//用戶已經明確禁止應用使用定位服務或者當前系統定位服務處於關閉狀態
// kCLAuthorizationStatusAuthorizedAlways NS_ENUM_AVAILABLE(NA, 8_0)//應用得到受權能夠一直使用定位服務,即便應用不在使用狀態
// kCLAuthorizationStatusAuthorizedWhenInUse NS_ENUM_AVAILABLE(NA, 8_0)//使用此應用過程當中容許訪問定位服務
// kCLAuthorizationStatusAuthorized NS_ENUM_DEPRECATED(10_6, NA, 2_0, 8_0, "Use kCLAuthorizationStatusAuthorizedAlways") = kCLAuthorizationStatusAuthorizedAlways//已經廢棄
四、檢查定位服務是否開啓
//GPS硬件打開 if (![CLLocationManager locationServicesEnabled]) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"GPS未開啓" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; }
五、請求數據
//實例化 self.locationManager = [[CLLocationManager alloc] init]; //GPS精確度 kCLLocationAccuracyBestForNavigation 導航級別(Best 最精肯定位)(HundredMeters 百米級)(Kilometer 公里級)(ThreeKilometers 3公里級)
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest]; //設置距離過濾, 移動多少距離觸發新的位置事件 [self.locationManager setDistanceFilter:100.f]; //設置響應的delegate self.locationManager.delegate = self;
六、爲獲取位置作好準備後,就能夠開始定位
//開啓定位服務 [self.locationManager startUpdatingLocation];
七、CLLocationManager將根據指定的參數在須要時利用GPS和/或Wi-Fi肯定當前的位置。應實現兩個委託方法,它們分別處理以下情形:位置管理器更新了當前位置或沒法更新當前位置。
獲取位置後,將調用:
//獲取到位置點 -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ NSLog(@"%@", locations.lastObject); //位置管理器經過數組locations提供多個位置,其中最後一個是最新的位置。
}
沒法更新當前位置將調用 :
//失敗的時候 -(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{ NSLog(@"%@", error); }
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ CLLocation *lastLocation = [locations lastObject]; if(lastLocation.horizontalAccuracy < 0 || lastLocation.horizontalAccu racy > 1000){
return;
}
NSLog(@">>>>%@",locations.lastObject); }
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{ [self.locationManager stopUpdatingLocation];
}
位置管理器委託可監控航向的變化,這頗有用。可以使用這些信息在地圖上標出用戶的前進路線 相對於正確路線的誤差。要獲取航向信息,須要讓位置管理器對其進行監視。還可設置⼀個可選的篩選器,這樣航向變化小於指定的度數,就不會獲取更新。
CLLocationDegrees degreesFilter = 2.0; if([CLLocationManager headingAvailable]) { [self.locationManager setHeadingFilter:degreesFilter]; [self.locationManager startUpdatingHeading]; }
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLH eading *)newHeading{ NSLog(@"new heading, magnetic%@",newHeading.magneticHeading); }
八、分析理解位置數據
CLLocationCoordinate2D coord = lastLocation.coordinate; NSLog(@"Locationlat/long: %f,%f",coord.latitude, coord.longitude);
CLLocationAccuracy horizontalAccuracy = lastLocation.horizontalAccuracy; NSLog(@"Horizontal accuracy: %f meters",horizontalAccuracy);
CLLocationDistance altitude = lastLocation.altitude; NSLog(@"Location altitude: %f meters",altitude); CLLocationAccuracy verticalAccuracy = lastLocation.verticalAccuracy; NSLog(@"Vertical accuracy: %f meters",verticalAccuracy);
九、重大位置變化通知
//開啓 [self.locationManager startMonitoringSignificantLocationChanges]; //停⽌ [self.locationManager stopMonitoringSignificantLocationChanges];
十、使用GPX文件進行位置測試
<?xml version="1.0"?> <gpx version="1.1" creator="Xcode"> <wpt lat="37.331705" lon="-122.030237"></wpt> </gpx>
2、顯示地圖
一、配置和定製MKMapKit
//經過UISegmentedControl切換地圖的區域 - (IBAction)mapTypeSelectionChanged:(id)sender {
UISegmentedControl *mapSelection = (UISegmentedControl *)sender; switch (mapSelection.selectedSegmentIndex) { case 0: [self.mapView setMapType:MKMapTypeStandard]; break;
case 1: [self.mapView setMapType:MKMapTypeSatellite]; break;
case 2: [self.mapView setMapType:MKMapTypeHybrid]; break; default: break; } }
//區域的中心點 CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(34.78, 113.68); //設置經緯度的跨度 MKCoordinateSpan span = MKCoordinateSpanMake(0.03, 0.03); //地圖顯示的區域 MKCoordinateRegion region = MKCoordinateRegionMake(coordinate, span); //設置地圖顯示區域 [self.mapView setRegion:region];
二、相應用戶交互
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{ MKCoordinateRegion newRegion = [mapView region]; CLLocationCoordinate2D center = newRegion.center; MKCoordinateSpan span = newRegion.span; NSLog(@"New map region center: <%f/%f>, span: <%f/%f>",center.latitude,center.longitude,span.latitudeDelta,span.longitudeDelta); }
3、地圖註釋和覆蓋層
一、添加註釋
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ //當前的最準確的位置點 CLLocation *location = locations.lastObject; //把當前位置做爲註釋添加上 MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init]; //位置指定爲當前位置 annotation.coordinate = location.coordinate; annotation.title = @"你好"; annotation.subtitle = @"這是銀行"; }
刪除註釋
 [self.mapView removeAnnotations:self.mapView.annotations];
自定義註釋
//遵照MKAnnotation協議的對象,能夠做爲註釋 @interface LEAnnotation : NSObject<MKAnnotation> //其隱性產生了一個get/set方法 @property(nonatomic)CLLocationCoordinate2D coordinate;
//在mapView文件
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
if ([annotation isKindOfClass:[LEAnnotation class]]) {
static NSString *Identifier = @"QYAnnotation";
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:Identifier];
if (!annotationView) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:Identifier];
}
annotationView.annotation = annotation;
annotationView.image = [UIImage imageNamed:@"currentlocation"];
return annotationView;
}
return nil;
}
二、可拖拽的註釋視圖
三、使用地圖覆蓋層
添加覆蓋層
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ CLLocation *location = locations.lastObject; //通過的位置點保存 [self.allLocation addObject:location]; //mkmappoint數組 MKMapPoint *mapArray = malloc(sizeof(MKMapPoint)*self.allLocation.count); for (int i = 0; i < self.allLocation.count; i++) { CLLocation *location = self.allLocation[i]; mapArray[i] = MKMapPointForCoordinate(location.coordinate); } //曲線覆蓋層 MKPolyline *polyline = [MKPolyline polylineWithPoints:mapArray count:self.allLocation.count]; free(mapArray); //添加覆蓋層 [self.mapView addOverlay:polyline]; }
當地圖須要顯示地圖覆蓋層的時候, 地圖視圖將調用委託⽅法mapView:viewForOverlay:,這個方法建立⼀個覆蓋層視圖,供地圖進行顯示。有三種形式:圓圈、多邊形、和折線;也可自定義形狀和覆蓋層。
//返回覆蓋層視圖 -(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{ if ([overlay isKindOfClass:[MKPolyline class]]) { MKPolyline *line = (MKPolyline *)overlay; //覆蓋層視圖,曲線 MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithPolyline:line]; renderer.lineWidth = 3.f; renderer.strokeColor = [UIColor blueColor]; //返回覆蓋層 return renderer; } return nil; }