iOS项目开发— CoreLocation的定位服务和地理编码与发编码实现
?
一、CoreLocation簡介
1.在移動互聯網時代,移動app能解決用戶的很多生活瑣事,比如
(1)導航:去任意陌生的地方
(2)周邊:找餐館、找酒店、找銀行、找電影院
?
2.在上述應用中,都用到了地圖和定位功能,在iOS開發中,要想加入這2大功能,必須基于2個框架進行開發
(1)Map Kit?:用于地圖展示
(2)Core Location?:用于地理定位
?
3.兩個熱門專業術語
(1)LBS?:Location Based Service(基于定位的服務)
(2)SoLoMo :Social Local Mobile(索羅門)
?
二、CoreLocation框架的使用
1.CoreLocation框架使用前提
(1)導入框架
?
說明:在Xcode5以后,不再需要我們手動導入
(2)導入主頭文件
#import <CoreLocation/CoreLocation.h>
?
2.CoreLocation框架使用須知
CoreLocation框架中所有數據類型的前綴都是CL
CoreLocation中使用CLLocationManager對象來做用戶定位
三、模擬位置
說明:在對程序進行測試的時候,設置手機模擬器的模擬位置(經緯度)
? ??
四、CoreLocation定位服務? ? ?1.CLLocationManager
CLLocationManager的常用操作和屬性
開始用戶定位- (void)startUpdatingLocation;
停止用戶定位- (void) stopUpdatingLocation;
說明:當調用了startUpdatingLocation方法后,就開始不斷地定位用戶的位置,中途會頻繁地調用代理的下面方法
-?(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations;
每隔多少米定位一次
@property(assign, nonatomic) CLLocationDistance distanceFilter;
定位精確度(越精確就越耗電)
@property(assign, nonatomic) CLLocationAccuracy desiredAccuracy;
?2.CLLocation
CLLocation用來表示某個位置的地理信息,比如經緯度、海拔等等
(1)經緯度?
@property(readonly, nonatomic) CLLocationCoordinate2D coordinate;
(2)海拔?
@property(readonly, nonatomic) CLLocationDistance altitude;
(3)路線,航向(取值范圍是0.0° ~ 359.9°,0.0°代表真北方向)
@property(readonly, nonatomic) CLLocationDirection course;
(4)行走速度(單位是m/s)
?@property(readonly, nonatomic) CLLocationSpeed speed;
(5)計算2個位置之間的距離
- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location方法
?
3.CLLocationCoordinate2D
CLLocationCoordinate2D是一個用來表示經緯度的結構體,定義如下
typedef struct {
? ? ? ? CLLocationDegrees latitude; // 緯度
? ? ? ? CLLocationDegrees longitude; // 經度
} CLLocationCoordinate2D;
一般用CLLocationCoordinate2DMake函數來創建CLLocationCoordinate2D
?
五、代碼示例
1 //? Created by 鑫 on 14-10-22. 2 //? Copyright (c) 2014年 梁镋鑫. All rights reserved. 3 // 4 5 #import "TXViewController.h" 6 #import <CoreLocation/CoreLocation.h> 7 @interface TXViewController ()<CLLocationManagerDelegate> 8 /** 9 ?*? 地理編碼 10 ?*/ 11 @property (nonatomic, strong) CLGeocoder *geocoder; 12 /** 13 ?*? 定位管里 14 ?*/ 15 @property (nonatomic, strong) CLLocationManager *locMgr; 16 @property(nonatomic ,strong)NSString *cityName; 17 18 @end 19 20 @implementation TXViewController 21 - (CLGeocoder *)geocoder 22 { 23 ? ? if (!_geocoder) { 24 ? ? ? ? self.geocoder = [[CLGeocoder alloc] init]; 25 ? ? } 26 ? ? return _geocoder; 27 } 28 ?#pragma mark-懶加載 29 - (CLLocationManager *)locMgr 30 { 31 #warning 定位服務不可用 32 ? ? if(![CLLocationManager locationServicesEnabled]) return nil; 33 ?? ? 34 ? ? if (!_locMgr) { 35 ? ? ? ? // 創建定位管理者 36 ? ? ? ? self.locMgr = [[CLLocationManager alloc] init]; 37 ? ? ? ? // 設置代理 38 ? ? ? ? self.locMgr.delegate = self; 39 ? ? } 40 ? ? return _locMgr; 41 } 42 43 - (void)viewDidLoad 44 { 45 ? ? [super viewDidLoad]; 46 // 開始定位用戶的位置 47 ? ? [self.locMgr startUpdatingLocation]; 48 ?? ? 49 ? ? // 開始監控某個位置 50 ? ? CLRegion *region = [[CLRegion alloc] init]; 51 ? ? /** 52 ?? ? ........ 53 ?? ? */ 54 ? ? [self.locMgr startMonitoringForRegion:region]; 55 ? ? //定位的精確度 56 ?? ? self.locMgr.desiredAccuracy=kCLLocationAccuracyThreeKilometers; 57 ?? ? 58 } 59 60 // 61 ///** 62 // *? 計算2個經緯度之間的直線距離 63 // */ 64 //- (void)countLineDistance 65 //{ 66 //? ? // 計算2個經緯度之間的直線距離 67 //? ? CLLocation *loc1 = [[CLLocation alloc] initWithLatitude:40 longitude:116]; 68 //? ? CLLocation *loc2 = [[CLLocation alloc] initWithLatitude:41 longitude:116]; 69 //? ? CLLocationDistance distance = [loc1 distanceFromLocation:loc2]; 70 //? ? NSLog(@"%f", distance); 71 //} 72 73 #pragma mark - CLLocationManagerDelegate 74 /** 75 ?*? 只要定位到用戶的位置,就會調用(調用頻率特別高)定位管理器 代理方法,定位完畢時侯調用 76 ?*? @param locations : 裝著CLLocation對象 77 ?*/ 78 - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations 79 { 80 ? ? // 1.取出位置對象 81 ? ? CLLocation *loc = [locations firstObject]; 82 ?? ? 83 ?? ? 84 ? ? // 2.取出經緯度 85 ? ? CLLocationCoordinate2D coordinate = loc.coordinate; 86 ? ? CLLocation *loc1 = [[CLLocation alloc] initWithLatitude:coordinate.latitude longitude:coordinate.longitude]; 87 ? ? //反地理編碼 88 ? ? [self.geocoder reverseGeocodeLocation:loc1 completionHandler:^(NSArray *placemarks, NSError *error) { 89 ?? ? ? ? CLPlacemark *pm = [placemarks firstObject]; 90 ? ? ? ? // 從字典中取出 state---->某某市 91 ?? ? ? ? NSString *cityName = pm.addressDictionary[@"State"]; 92 ? ? ? ? self.cityName = cityName; 93 ? ? ? ? NSLog(@"%@",self.cityName); 94 ? ? ? ? NSLog(@"%@",loc1); 95 ? ? ? ? NSLog(@"%@",pm.name); 96 ? ? }]; 97 ?? ? 98 ? ? // 3.打印經緯度 99 ? ? NSLog(@"didUpdateLocations------%f %f", coordinate.latitude, coordinate.longitude); 100 ?? ? 101 ? ? // 停止定位(省電措施:只要不想用定位服務,就馬上停止定位服務) 102 ? ? [manager stopUpdatingLocation]; 103 } 104 105 106 @end View Code?
打印查看:
代碼說明:
1.關于代理方法
需要設置代理,通過代理告訴用戶當前的位置,有兩個代理方法:
locations參數里面裝著CLLocation對象
其中后者是一個過期的方法,在新的方法(第一個)中使用了一個數組來替代。 說明:該方法在當定位到用戶的位置時就會調用,調用比較頻繁 注意:不要使用局部變量(創建位置管理器),因為局部變量的方法結束它就被銷毀了。建議使用一個全局的變量,且只創建一次就可以了(使用懶加載)。 2.定位的精度 3.如果發現自己的定位服務沒有打開,那么應該提醒用戶打開定位服務功能。 4.定位服務是比較耗電的,如果是做定位服務(沒必要實時更新的話),那么定位了用戶位置后,應該停止更新位置。 六、用戶隱私的保護1.權限設置說明
從iOS 6開始,蘋果在保護用戶隱私方面做了很大的加強,以下操作都必須經過用戶批準授權
(1)要想獲得用戶的位置
(2)想訪問用戶的通訊錄、日歷、相機、相冊等
當想訪問用戶的隱私信息時,系統會自動彈出一個對話框讓用戶授權
注意:一旦用戶選擇了“Don’t Allow”,意味著你的應用以后就無法使用定位功能,且當用戶第一次選擇了之后,以后就再也不會提醒進行設置。
因此在程序中應該進行判斷,如果發現自己的定位服務沒有打開,那么應該提醒用戶打開定位服務功能。
CLLocationManager有個類方法可以判斷當前應用的定位功能是否可用+ (BOOL)locationServicesEnabled;
常用的方法:截圖告訴用戶,應該怎么打開授權2.開發者可以在Info.plist中設置NSLocationUsageDescription說明定位的目的(Privacy - Location Usage Description)
說明:(1)以上iOS7可行,iOS8變了,配置變成如下
? ? ? ? (2)這里的定位服務是基于網絡的。通常定位服務可以是基于GPS、基站或者是網絡的。
?
七、CoreLocation地理編碼
?
CLGeocoder:地理編碼器,其中Geo是地理的英文單詞Geography的簡寫。
1.使用CLGeocoder可以完成“地理編碼”和“反地理編碼”
地理編碼:根據給定的地名,獲得具體的位置信息(比如經緯度、地址的全稱等)
反地理編碼:根據給定的經緯度,獲得具體的位置信息
?
(1)地理編碼方法
- (void)geocodeAddressString:(NSString *)addressString completionHandler:(CLGeocodeCompletionHandler)completionHandler;?
(2)反地理編碼方法
- (void)reverseGeocodeLocation:(CLLocation *)location completionHandler:(CLGeocodeCompletionHandler)completionHandler;
?
2.CLGeocodeCompletionHandler
當地理\反地理編碼完成時,就會調用CLGeocodeCompletionHandler
這個block傳遞2個參數
error?:當編碼出錯時(比如編碼不出具體的信息)有值
placemarks?:里面裝著CLPlacemark對象
?
? ?3.CLPlacemark
說明:CLPlacemark的字面意思是地標,封裝詳細的地址位置信息
地理位置? @property (nonatomic, readonly) CLLocation *location;
區域 ?@property (nonatomic, readonly) CLRegion *region;
詳細的地址信息???@property (nonatomic, readonly) NSDictionary *addressDictionary;
地址名稱 @property (nonatomic, readonly) NSString *name;
城市 @property (nonatomic, readonly) NSString *locality;
?
二、代碼示例:
在storyboard中搭建界面如下:
實現代碼:
1 //? Created by 鑫 on 14-10-22. 2 //? Copyright (c) 2014年 梁镋鑫. All rights reserved. 3 // 4 5 #import "TXViewController.h" 6 #import <CoreLocation/CoreLocation.h> 7 @interface TXViewController () 8 9 @property (nonatomic, strong) CLGeocoder *geocoder; 10 11 #pragma mark - 地理編碼 12 - (IBAction)geocode; 13 @property (weak, nonatomic) IBOutlet UITextField *addressField; 14 @property (weak, nonatomic) IBOutlet UILabel *longitudeLabel; 15 @property (weak, nonatomic) IBOutlet UILabel *latitudeLabel; 16 @property (weak, nonatomic) IBOutlet UILabel *detailAddressLabel; 17 18 #pragma mark - 反地理編碼 19 - (IBAction)reverseGeocode; 20 @property (weak, nonatomic) IBOutlet UITextField *longtitudeField; 21 @property (weak, nonatomic) IBOutlet UITextField *latitudeField; 22 @property (weak, nonatomic) IBOutlet UILabel *reverseDetailAddressLabel; 23 24 @end 25 26 @implementation TXViewController 27 28 - (CLGeocoder *)geocoder 29 { 30 ? ? if (!_geocoder) { 31 ? ? ? ? self.geocoder = [[CLGeocoder alloc] init]; 32 ? ? } 33 ? ? return _geocoder; 34 } 35 36 - (void)viewDidLoad 37 { 38 ? ? [super viewDidLoad]; 39 ?? ? 40 } 41 42 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 43 { 44 ? ? [self.view endEditing:YES]; 45 } 46 47 /** 48 ?*? 地理編碼 49 ?*/ 50 - (IBAction)geocode { 51 ?? ? //1.獲得輸入的地址 52 ? ? NSString *address = self.addressField.text; 53 ? ? if (address.length == 0) return; 54 ? ? //2.開始地理編碼 55 ?? ? ? ? //說明:調用下面的方法開始編碼,不管編碼是成功還是失敗都會調用block中的方法 56 ? ? [self.geocoder geocodeAddressString:address completionHandler:^(NSArray *placemarks, NSError *error) { 57 ? ? ? ? //如果有錯誤信息,或者是數組中獲取的地名元素數量為0,那么說明沒有找到 58 ? ? ? ? if (error) { // 有錯誤(地址亂輸入) 59 ? ? ? ? ? ? self.detailAddressLabel.text = @"你找的地址可能只在外星球才能找到!!!"; 60 ? ? ? ? } else { // 編碼成功 找到了具體的位置信息 61 ? ? ? ? ? ? // 取出最前面的地址 62 ? ? ? ? ? ? CLPlacemark *pm = [placemarks firstObject]; 63 ?? ? ? ? ? ? 64 ? ? ? ? ? ? // 設置經緯度 65 ? ? ? ? ? ? self.latitudeLabel.text = [NSString stringWithFormat:@"%.1f", pm.location.coordinate.latitude]; 66 ? ? ? ? ? ? self.longitudeLabel.text = [NSString stringWithFormat:@"%.1f", pm.location.coordinate.longitude]; 67 ?? ? ? ? ? ? 68 ? ? ? ? ? ? // 設置具體地址 69 ? ? ? ? ? ? self.detailAddressLabel.text = pm.name; 70 ?? ? ? ? ? ? 71 ? ? ? ? ? ? //打印查看找到的所有的位置信息 72 ? ? ? ? ? ? //? ? ? ? ? ? NSLog(@"總共找到%d個地址", placemarks.count); 73 ? ? ? ? ? ? // 74 ? ? ? ? ? ? //? ? ? ? ? ? for (CLPlacemark *pm in placemarks) { 75 ? ? ? ? ? ? //? ? ? ? ? ? ? ? NSLog(@"-----地址開始----"); 76 ? ? ? ? ? ? // 77 ? ? ? ? ? ? //? ? ? ? ? ? ? ? NSLog(@"%f %f %@", pm.location.coordinate.latitude, pm.location.coordinate.longitude, pm.name); 78 ? ? ? ? ? ? // 79 ? ? ? ? ? ? //? ? ? ? ? ? ? ? [pm.addressDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { 80 ? ? ? ? ? ? //? ? ? ? ? ? ? ? ? ? NSLog(@"%@ %@", key, obj); 81 ? ? ? ? ? ? //? ? ? ? ? ? ? ? }]; 82 ? ? ? ? ? ? // 83 ? ? ? ? ? ? //? ? ? ? ? ? ? ? NSLog(@"-----地址結束----"); 84 ? ? ? ? ? ? //? ? ? ? ? ? } 85 ? ? ? ? } 86 ? ? }]; 87 } 88 89 /** 90 ?*? 反地理編碼 91 ?*/ 92 - (IBAction)reverseGeocode { 93 ? ? // 1.包裝位置 94 ? ? CLLocationDegrees latitude = [self.latitudeField.text doubleValue]; 95 ? ? CLLocationDegrees longitude = [self.longtitudeField.text doubleValue]; 96 ? ? CLLocation *loc = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude]; 97 ?? ? 98 ? ? // 2.反地理編碼 99 ? ? [self.geocoder reverseGeocodeLocation:loc completionHandler:^(NSArray *placemarks, NSError *error) { 100 ? ? ? ? if (error) { // 有錯誤(地址亂輸入) 101 ? ? ? ? ? ? self.reverseDetailAddressLabel.text = @"你找的地址可能來自星星的!!!"; 102 ? ? ? ? } else { // 編碼成功 103 ? ? ? ? ? ? // 取出最前面的地址 104 ? ? ? ? ? ? CLPlacemark *pm = [placemarks firstObject]; 105 ?? ? ? ? ? ? 106 ? ? ? ? ? ? // 設置具體地址 107 ? ? ? ? ? ? self.reverseDetailAddressLabel.text = pm.name; 108 ? ? ? ? ? ? //? ? ? ? ? ? NSLog(@"總共找到%d個地址", placemarks.count); 109 ? ? ? ? ? ? // 110 ? ? ? ? ? ? //? ? ? ? ? ? for (CLPlacemark *pm in placemarks) { 111 ? ? ? ? ? ? //? ? ? ? ? ? ? ? NSLog(@"-----地址開始----"); 112 ? ? ? ? ? ? // 113 ? ? ? ? ? ? //? ? ? ? ? ? ? ? NSLog(@"%f %f %@", pm.location.coordinate.latitude, pm.location.coordinate.longitude, pm.name); 114 ? ? ? ? ? ? // 115 ? ? ? ? ? ? //? ? ? ? ? ? ? ? [pm.addressDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { 116 ? ? ? ? ? ? //? ? ? ? ? ? ? ? ? ? NSLog(@"%@ %@", key, obj); 117 ? ? ? ? ? ? //? ? ? ? ? ? ? ? }]; 118 ? ? ? ? ? ? // 119 ? ? ? ? ? ? //? ? ? ? ? ? ? ? NSLog(@"-----地址結束----"); 120 ? ? ? ? ? ? //? ? ? ? ? ? } 121 ? ? ? ? } 122 ? ? }]; 123 } 124 @end 125 ? View Code?
?
實現效果:
(1)地理編碼:(地名->經緯度坐標)
打印輸出:
(2)反地理編碼:(經緯度—>地名)
(3)注意:搜索的所有結果都是在中國境內的,因為蘋果在中國的地圖服務商是高德地圖。
?
?
轉載于:https://www.cnblogs.com/asd5551680/p/4182005.html
總結
以上是生活随笔為你收集整理的iOS项目开发— CoreLocation的定位服务和地理编码与发编码实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 你理解我的意思么?
- 下一篇: 使用polar si9000计算差分阻抗