IOS学习之十二:Core Location定位和MapKit视图使用
iPhone中的基于位置服务开发的应用其实挺多的。
但是那种能显示密集型周边的信息或者说是资料数据的应用,
还真不知道是通过的是类似于webService还是内置类似于地图导航功能的数据包。
但是对于简单如何上手这方面的开始,我们还是要接触下的。
总的来说,我们这类应用的会涉及到核心的两块内容。
1.位置定位(最简单就是当前应用所有者所持设备的地理位置),主要用到的API类 CLLicationManager。
在其他比如(Android位置类开发),我们知道实现定位的方式有gprs,网络,蜂窝式,基站等。并且是可以通过自己选的。
ios中就却直接hide或者说是简单化了这种定位方式。
只需我们设置一些参数后,系统自动会做出最切当的反应。
2.位置确定了,那么下一步就是显示给用户了。显示的视图,这边用到API类MapKit。
比如我们定位了一个经度 30.002,纬度为199.232.最简单的,我们直接在提供的视图上定位到这个点。
但是我们知道,更多的时候,我们希望显示这个点的更多数据信息(比如街道,XXX路),更甚至是周边的。
这个就需要庞大的数据包支持了,因为我没做过这方面的,只是简单知道可以通过google公开的一个web端接口获取数据。
一:首先简单介绍下CLLicationManager类的常用
开启定位服务:
- self.locationManager = [[CLLocationManager alloc]init];
- if (![CLLocationManager locationServicesEnabled]) {
- NSLog(@"定位不可用~");
- }else {
- //设置代理
- [self.locationManager setDelegate:self];
- //设置精准度,
- [self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
- [self.locationManager startUpdatingLocation];
- }
self.locationManager = [[CLLocationManager alloc]init]; if (![CLLocationManager locationServicesEnabled]) { NSLog(@"定位不可用~"); }else { //设置代理 [self.locationManager setDelegate:self]; //设置精准度, [self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest]; [self.locationManager startUpdatingLocation]; }
初始化了位置管理器,判断设备的定位功能是否开启开启的话设置代理,精度等参数后,开始服务。
实现代理类方法,获取返回参数:
- #pragma mark-
- #pragma locationManagerDelegate methods
- - (void)locationManager:(CLLocationManager *)manager
- didUpdateToLocation:(CLLocation *)newLocation
- fromLocation:(CLLocation *)oldLocation
- {
- self.coordinate = [newLocation coordinate];
- self.altitude = [newLocation altitude];
- NSString *lat = [[NSString alloc] initWithFormat:@"%f",self.coordinate.latitude];
- NSString *lon = [[NSString alloc] initWithFormat:@"%f",self.coordinate.longitude];
- NSString *alt = [[NSString alloc] initWithFormat:@"%f",self.altitude];
- //更新定位信息方法
- NSLog(@"delegate %f,%f",self.coordinate.latitude,self.coordinate.longitude);
- self.latitudeText.text = lat;
- self.longitudeText.text = lon;
- self.altitudeText.text = alt;
- [lat release];
- [lon release];
- [alt release];
- }
- - (void)locationManager:(CLLocationManager *)manager
- didFailWithError:(NSError *)error
- {
- //定位失败
- }
#pragma mark- #pragma locationManagerDelegate methods - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { self.coordinate = [newLocation coordinate]; self.altitude = [newLocation altitude]; NSString *lat = [[NSString alloc] initWithFormat:@"%f",self.coordinate.latitude]; NSString *lon = [[NSString alloc] initWithFormat:@"%f",self.coordinate.longitude]; NSString *alt = [[NSString alloc] initWithFormat:@"%f",self.altitude]; //更新定位信息方法 NSLog(@"delegate %f,%f",self.coordinate.latitude,self.coordinate.longitude); self.latitudeText.text = lat; self.longitudeText.text = lon; self.altitudeText.text = alt; [lat release]; [lon release]; [alt release]; } - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { //定位失败 }
返回的一个CLLocation 类型包含常用的几种数据,经纬度,运动速率,海拔,方向等,我们可以按需要来获取。
二:用MapKit来显示
第一步就是添加一个mapView视图
然后也是很简单的几行代码即显示位置点。
对于将经纬度转化成友善的地理信息,首先我们来看个最传统的例子,既我们将获取的经纬度封装成一个网络请求到google的map服务,
返回对应的地址信息。
- latNum = [[NSNumber alloc] initWithFloat:lat];
- lonNum = [[NSNumber alloc] initWithFloat:lon];
- NSURL * aurl = [NSURL URLWithString:[NSString stringWithFormat:
- @"http://ditu.google.com/maps/geo?q=%@,%@&output=json&oe=utf8&hl=zh-CN&sensor=false",latNum,lonNum]];
- NSURLRequest *request = [[NSURLRequest alloc] initWithURL:aurl];
- self.connection1=[NSURLConnection connectionWithRequest:request delegate:self];
latNum = [[NSNumber alloc] initWithFloat:lat]; lonNum = [[NSNumber alloc] initWithFloat:lon]; NSURL * aurl = [NSURL URLWithString:[NSString stringWithFormat: @"http://ditu.google.com/maps/geo?q=%@,%@&output=json&oe=utf8&hl=zh-CN&sensor=false",latNum,lonNum]]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:aurl]; self.connection1=[NSURLConnection connectionWithRequest:request delegate:self];
请求很简单,将经纬度放置进请求中。
上后上面就是一个传统的网络请求吧,
然后我们在NSURLConnection的代理方法中处理返回数据
- - (void)connectionDidFinishLoading:(NSURLConnection *)connection
- {
- NSString *jsonString = [[NSString alloc] initWithData:self.amutabledata encoding:NSUTF8StringEncoding];
- NSDictionary * jsonDic = [jsonString JSONValue];
- NSArray * jsonarr = [jsonDic objectForKey:@"Placemark"];
- NSDictionary *dic2 = [jsonarr objectAtIndex:0];
- NSString *name1 = [dic2 objectForKey:@"address"];
- }
- (void)connectionDidFinishLoading:(NSURLConnection *)connection { NSString *jsonString = [[NSString alloc] initWithData:self.amutabledata encoding:NSUTF8StringEncoding]; NSDictionary * jsonDic = [jsonString JSONValue]; NSArray * jsonarr = [jsonDic objectForKey:@"Placemark"]; NSDictionary *dic2 = [jsonarr objectAtIndex:0]; NSString *name1 = [dic2 objectForKey:@"address"]; }
这边提下,googlemap服务请求可以以xml协议格式,也可以json协议格式。因为这边我用了json的,然后对于json的解析处理类用了SBJSON包。
具体你要解析出的内容你可以先在先将内容打印出来或是在浏览器请求后看下然后选择性解析。
然后是昨天在翻开发秘籍那本书,看到了关于这块的内容:逆向地理编码。
其实还是基于googlemap服务,只是IOS提供了一个简化的API,可供调用。
MKReverseGeocoder和他的一个代理类。原理基本和上面是一模一样。大家直接用下这两个类就明白了。
但是在ios5.0以上发现这几个类又被将之遗弃被新的CLGeocoder类代替并且去掉了代理类这一步。
- [CLGeocoder alloc] reverseGeocodeLocation:(CLLocation *) completionHandler:^(NSArray *placemarks, NSError *error)completionHandler
[CLGeocoder alloc] reverseGeocodeLocation:(CLLocation *) completionHandler:^(NSArray *placemarks, NSError *error)completionHandler }
第一个参数我们都懂,第二个参数是个block对象,至于什么是block,详情就查看文档。
现在我们回到这段内容的最开始,即在一个视图上显示。
- MKCoordinateSpan span;
- span.latitudeDelta = 0.05;
- span.longitudeDelta = 0.05;
- //设置可调跨度,偏移量,越小越精确
- MKCoordinateRegion region ={self.coordinate,span};
- //确定一个屏幕坐标
- [self.mapKit setRegion:region];
- self.mapKit.showsUserLocation = YES;//当前位置显示小蓝点
MKCoordinateSpan span; span.latitudeDelta = 0.05; span.longitudeDelta = 0.05; //设置可调跨度,偏移量,越小越精确 MKCoordinateRegion region ={self.coordinate,span}; //确定一个屏幕坐标 [self.mapKit setRegion:region]; self.mapKit.showsUserLocation = YES;//当前位置显示小蓝点
在mapView显示的位置点是在视图的center点,确定这个点需要的两个参数,一个是经纬度,一个是跨度,其实说白越小越精确,越精确就是把视图放大放大~
反正还有很多细节的参数,在真正需要去设计这样一个应用时,再去慢慢调试。
最后我们在看下如何在地图上创建一个大头针。
先看下效果图:
这就是一般说的注解,自定义一个大头针,实现一个MKAnnotation协议。
- //
- // MyPin.h
- // MapKitTest
- //
- // Created by Nono on 12-5-17.
- // Copyright (c) 2012年 NonoWithLilith. All rights reserved.
- //
- #import <Foundation/Foundation.h>
- #import <MapKit/MapKit.h>
- @interface MyPin : NSObject<MKAnnotation>
- - (id)initWithCoordinate2D:(CLLocationCoordinate2D)dinate
- tittle:(NSString*)title subtitle:(NSString*)subtitle;
- @end
// // MyPin.h // MapKitTest // // Created by Nono on 12-5-17. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import <Foundation/Foundation.h> #import <MapKit/MapKit.h> @interface MyPin : NSObject<MKAnnotation> - (id)initWithCoordinate2D:(CLLocationCoordinate2D)dinate tittle:(NSString*)title subtitle:(NSString*)subtitle; @end
- //
- // MyPin.m
- // MapKitTest
- //
- // Created by Nono on 12-5-17.
- // Copyright (c) 2012年 NonoWithLilith. All rights reserved.
- //
- #import "MyPin.h"
- @implementation MyPin
- @synthesize coordinate;
- @synthesize title = _title;
- @synthesize subtitle = _subtitle;
- - (id)initWithCoordinate2D:(CLLocationCoordinate2D)dinate
- tittle:(NSString*)title subtitle:(NSString*)subtitle
- {
- if(self = [super init])
- {
- _title = title;
- _subtitle=subtitle;
- coordinate = dinate;
- }
- return self;
- }
- - (void)dealloc
- {
- [self.title release];
- [self.subtitle release];
- [super dealloc];
- }
- @end
// // MyPin.m // MapKitTest // // Created by Nono on 12-5-17. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import "MyPin.h" @implementation MyPin @synthesize coordinate; @synthesize title = _title; @synthesize subtitle = _subtitle; - (id)initWithCoordinate2D:(CLLocationCoordinate2D)dinate tittle:(NSString*)title subtitle:(NSString*)subtitle { if(self = [super init]) { _title = title; _subtitle=subtitle; coordinate = dinate; } return self; } - (void)dealloc { [self.title release]; [self.subtitle release]; [super dealloc]; } @end
- CLLocationCoordinate2D anndiante;
- //为了显示比较清晰不和定位点重叠
- anndiante.latitude = self.coordinate.latitude + 0.0011;
- anndiante.longitude = self.coordinate.longitude + 0.0012;
- MyPin *pin = [[MyPin alloc] initWithCoordinate2D:anndiante tittle:@"测试title" subtitle:@"测试子title"];
- [self.mapKit addAnnotation:pin];
- [pin release];
CLLocationCoordinate2D anndiante; //为了显示比较清晰不和定位点重叠 anndiante.latitude = self.coordinate.latitude + 0.0011; anndiante.longitude = self.coordinate.longitude + 0.0012; MyPin *pin = [[MyPin alloc] initWithCoordinate2D:anndiante tittle:@"测试title" subtitle:@"测试子title"]; [self.mapKit addAnnotation:pin]; [pin release];
当然对于跳出视图你可以做更多的添加以及视图自定义。
针对于Core Location和MapKit的编程基础就是这些。因为其实我的下一个项目中并不需要用到,也不做太对深入,
其实开发秘籍这本书上的细节对这块描述还有很多。看来这本熟当做以后的参考书还是不错的。
http://blog.csdn.net/nono_love_lilith/article/details/7588696