工作中遇到關於地圖定位的問題,現在就來總結一下,沒接觸這塊之前一直覺得地圖或者是百度地圖都是很高大上的東西,非常的難,在百度以及自己試驗過之後發現並沒有想象中的那麼困難。
我以前以爲如果要使用百度定位就需要安裝百度地圖,其實不是的,蘋果系統自帶了定位功能,不需要依賴任何其他的定位軟件就可以定位到具體的經緯度。百度地圖也是在蘋果系統自帶的定位功能上進行了一些更強大的功能的封裝,以便用戶使用起來更加方便。
本文中主要實現通過定位獲取的經緯度來得到具體街道詳情,以及通過街道信息獲得經緯度兩種CoreLocation地理編碼的方式,廢話不多說,下面來講解實現方式。
首先導入定位需要用到的CoreLocation.framework框架;(選中項目名-》General-》Linked Frameworks and Libraries點那個+號搜出CoreLocation.framework確定)在.h文件裏面引入頭文件
<strong>#import <UIKit/UIKit.h>
#import "CoreLocation/CoreLocation.h"
@interface LocationViewController : UIViewController<CLLocationManagerDelegate>
@end</strong>
然後我們就來做一下定位的操作,
@interface LocationViewController ()
//位置管理
@property (strong, nonatomic) CLLocationManager *locationManager;
//定時器
@property (strong, nonatomic) NSTimer *timer;
@end
新建一個可以切換狀態的按鈕放在屏幕中間,同時初始化計時器(3秒執行一次,可循環):
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton *offbtn = [UIButton buttonWithType:UIButtonTypeCustom];
offbtn.frame = CGRectMake(110, 80, 100, 50);
[offbtn setBackgroundColor:[UIColor redColor]];
[offbtn setTitle:@"開啓定位" forState:UIControlStateNormal];
[offbtn setTitle:@"取消定位" forState:UIControlStateSelected];
[offbtn addTarget:self action:@selector(changeState:) forControlEvents:UIControlEventTouchUpInside];
[offbtn addTarget:self action:@selector(startTimer:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:offbtn];
_timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(startLocation) userInfo:nil repeats:YES];
// [self startLocation];
// Do any additional setup after loading the view.
//將定時器加入到程序主循環中
// [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
//取消定時器,徹底關閉,定時器從主循環中移除
// [_timer invalidate];
// _timer = nil;
}
在這裏我不把定時器加入主循環裏面,我通過按鈕切換來開啓關閉計時器,要是想把定時器加入主循環中的可以使用上面的方法,就不需要再調用開啓定時器的方法了。
假如是ios8的sdk就需要加判斷,首先在Info.plist裏面添加一個NSLocationAlwaysUsageDescription :YES如下:
- (void)changeState:(UIButton*)btn
{
[btn setSelected:!btn.selected];
}
- (void)startTimer:(UIButton*)btn
{
if (btn.selected) {
//開啓定時器
[_timer setFireDate:[NSDate distantPast]];
}else{
//關閉定時器
[_timer setFireDate:[NSDate distantFuture]];
}
}
- (void)startLocation
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
//這裏設置爲最高精度定位
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
//設備移動10米通知代理器更新位置
self.locationManager.distanceFilter = 10.0f;<p style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; font-family: Menlo;"> <span style="color: #bb2ca2">if</span> (<span style="color: #78492a">iOS8</span>) {</p><p style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; font-family: Menlo; color: rgb(0, 132, 0);"><span style="color: #000000"> </span>// [self.locationManager requestWhenInUseAuthorization];// <span style="font-family: 'Heiti SC Light';">前臺定位</span></p><p style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; font-family: Menlo; color: rgb(61, 29, 129);"><span style="color: #000000"> <span style="white-space:pre"> </span>[</span><span style="color: #bb2ca2">self</span><span style="color: #000000">.</span><span style="color: #4f8187">locationManager</span><span style="color: #000000"> </span>requestAlwaysAuthorization<span style="color: #000000">];</span><span style="color: #008400">// </span><span style="font-family: 'Heiti SC Light'; color: rgb(0, 132, 0);">前後臺同時定位</span></p><p style="margin-top: 0px; margin-bottom: 0px; font-size: 11px; font-family: Menlo;"> }</p> //啓動定位
[self.locationManager startUpdatingLocation];
}
//定位代理經緯度回調
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
//此處locations存儲了持續更新的位置座標值,取最後一個值爲最新位置,如果不想讓其持續更新位置,則在此方法中獲取到一個值之後讓locationManager stopUpdatingLocation
// CLLocation *currentLocation = [locations lastObject];
CLLocation *currentLocation = [[CLLocation alloc]initWithLatitude:31.00927 longitude:121.40582];//如果使用模擬器不能定位的機器
NSLog(@"%@",[NSString stringWithFormat:@"緯度:%3.5f\n經度:%3.5f",currentLocation.coordinate.latitude,currentLocation.coordinate.longitude]);
// 獲取當前所在的城市名
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
//根據經緯度反向地理編譯出地址信息
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error)
{
for (CLPlacemark * placemark in placemarks) {
NSString *city = placemark.locality;
if (!city) {
//四大直轄市的城市信息無法通過locality獲得,只能通過獲取省份的方法來獲得(如果city爲空,則可知爲直轄市)
city = placemark.administrativeArea;
}
NSLog(@"address = %@\n",placemark.name);
NSDictionary *dictionary = [placemark addressDictionary];
// Country(國家) State(省) locality(市) SubLocality(區)
NSLog(@"%@%@%@",[dictionary objectForKey:@"State"], city,placemark.subLocality);
}
if (error == nil && [placemarks count] == 0)
{
NSLog(@"No results were returned.");
}
else if (error != nil)
{
NSLog(@"An error occurred = %@", error);
}
}];
//系統會一直更新數據,直到選擇停止更新,因爲我們只需要獲得一次經緯度即可,所以獲取之後就停止更新
[manager stopUpdatingLocation];
}
需要獲取其他的信息可以到CLPlacemark裏面最下面去找自己想要的信息,不知道意思可以全部打印出來然後再取捨,下面再通過已知的位置來獲取經緯度信息
插一點調試的小問題:如果用真機調試的話就可以用[location lastObject],我用模擬器調試就會自己制定一個經緯度運行,這裏要選中模擬器,在調試-》位置-》自定位置裏面隨便輸入一個(操作如下),這裏不指定還是有問題,下面的一個網友說的很詳細,我用的是無線網,也不知道是不是這個問題,大家自定義地址湊合着調試。
下面地理位置編碼,我直接加了一個方法,直接把startLocation改成下面的方法名就可以了:
- (void)geocode
{
//1.輸入的要定位的地址
NSString *address = @"上海市閔行區江川路690號";
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:address completionHandler:^(NSArray *placemarks, NSError *error) {
if (error || placemarks.count == 0) {
return ;
}else {//編碼成功
for (CLPlacemark *placemark in placemarks) {
NSString *city = placemark.locality;
if (!city) {
//四大直轄市的城市信息無法通過locality獲得,只能通過獲取省份的方法來獲得(如果city爲空,則可知爲直轄市)
city = placemark.administrativeArea;
}
NSLog(@"address = %@\n",placemark.name);
NSDictionary *dictionary = [placemark addressDictionary];
// Country(國家) State(省) locality(市) SubLocality(區)
NSLog(@"地理編碼:%@%@%@",[dictionary objectForKey:@"State"], city,placemark.subLocality);
}
//取出獲取的地理信息數組中的最後定位的
CLPlacemark *lastPlacemark = [placemarks lastObject];
CLLocationDegrees latitude = lastPlacemark.location.coordinate.latitude;
CLLocationDegrees longitude = lastPlacemark.location.coordinate.longitude;
NSLog(@"%@",[NSString stringWithFormat:@"緯度:%3.5f\n經度:%3.5f",latitude,longitude]);
}
}];
}
打印結果如下(3秒定位一次):