定位核心与地图
Core Location以及Map框架包通常能给我们的应用程序添加定位和地图相关的服务。
Core Location框架包通常是使用硬件设备来进行定位服务的,map框架包通常能够使你的应用程序做一些地图展示与交互的相关功能。地图的定位服务一般需要依赖设备的硬件组成部分。所以必须要导入Core Location 和Map这两个框架包。
#import <Core Location/CoreLocation.h>
#import<MapKit/MapKit.h>
创建一个地图的视图
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
@interface ViewController : UIViewController
@property(nonatomic,strong)MKMapView *myMapView;
@end
#import "ViewController.h"
@implementation ViewController
@synthesize myMapView;
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
myMapView = [[MKMapView alloc]initWithFrame:self.view.bounds];
myMapView.mapType = MKMapTypeStandard;//普通地图(默认)
myMapView.mapType = MKMapTypeSatellite;//卫星云图
myMapView.mapType = MKMapTypeHybrid;//普通类型来显示普通地图覆盖于卫星云图之上,展现属于复合形式。
myMapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:myMapView];
}
-(BOOL)shouldAutorotateToOnterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
return YES;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
捕获Map视图上的一些动作事件
实现MKMapViewDelegate协议里面的相关方法
mapViewWillStartLoadingMap: 这个方法是当地图界面要加载的时候会调用。
mapView:viewForAnnotation: 这个方法是当地图上有一些动画效果展示或者加载时候会调用这个方法。
mapViewWillStartLocatingUser: 这个方法是准备进行一个位置定位的时候会调用的方法。
mapView:regionDidChangeAnimated:这个方法调用,一般是当用户的地理位置发生变化的时候会调用。
用硬件设备获取当前用户的地理位置
使用CLLocationManager这个类,参考代码如下:
@interface ViewController : UIViewController<MKMapViewDelegate,CLLocationManagerDelegate>
@property(nonatomic,strong)MKMapView *myMapView;
@property(nonatomic,strong)CLLocationManager *myLocationManager;
@end
if([CLLocationManager locationServicesEnabled]){
myLocationManager = [[CLLocationManager alloc]init];
myLocationManager.delegate = self;
myLocationManager.purpose = @"To provide functionality based on user's current location.";
[myLocationManager startUpdatingLocation];
}else{
NSLog(@"Location services are not enabled");
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
NSLog(@"Latitude = %f",newLocation.coordinate.latitude);
NSLog(@"Longitude = %f",newLocation.coordinate.longitude);
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
}
CLLocationManager的startUpdateLocation 方法通过它的代理 didUpdateToLocation:fromLocation:和locationManager:didFailWithError:方法来报告用户定位成功或失败。
在地图视图上添加锚点
创建一个类,命名为MyAnnotation,实现MKAnnotation协议。
给这个类定义一个类型为CLLocationCoordinate2D的属性,命名为coordinate。特别要注意这个参数需要标示为只读类型的。因为MKAnnotation这个协议中定义的Coordinate也是只读类型的。
定义两个NSString类型的属性,分别命名为title 和 subtitle。这两个参数用来保存锚点的标题和内容信息。
给这个类添加一个初始化方法,这个方法需要传递一个CLLocationCoordinate2D类型的参数,在这个方法中把CLLocationCoordinate2D的属性传递进来,由于这个属性是只读的,它并不能在这个类的以外进行赋值。因此这个初始化方法也就是一个桥梁,使我们能够正常的往这个子类中进行传值,同理,title和subtitle也要进行类似操作。
初始化myAnnotation这个类,然后把他添加到你的地图中,通过Annotation这个方法。
相关代码如下:
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface MyAnnotation : NSObject<MKAnnotation>
@property(nonatomic,readonly)CLLocationCoordinate2D coordinate;
@property(nonatomic,copy,readonly)NSString *title;
@property(nonatomic,copy,readonly)NSString *subtitle;
-(id)initWithCoordinates:(CLLocationCoordinate2D)paramCoordinates title:(NSString *)paramTitle subTitle:(NSString*)paramSubTitle;
@end
#import "MyAnnotation.h"
@interface MyAnnotation ()
@end
@implementation MyAnnotation
CLLocationCoordinate2D coordinate;
@synthesize coordinate,title,subtitle;
-(id)initWithCoordinates:(CLLocationCoordinate2D)paramCoordinates title:(NSString *)paramTitle subTitle:(NSString*)paramSubTitle{
self = [super init];
if(self != nil){
coordinate = paramCoordinates;
title = paramTitle;
subtitle = paramSubTitle;
}
return (self);
}
@end
#import <UIKit/UIKit.h>
#import "MyAnnotation.h"
@interface MapViewController : UIViewController<MKMapViewDelegate>
@property(nonatomic,strong)MKMapView *myMapView;
@end
#import "MapViewController.h"
@interface MapViewController ()
@end
@implementation MapViewController
@synthesize myMapView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
myMapView = [[MKMapView alloc]initWithFrame:self.view.bounds];
myMapView.delegate = self;
myMapView.mapType = MKMapTypeStandard;
myMapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:myMapView];
CLLocationCoordinate2D location = CLLocationCoordinate2DMake(50.82191692907181, -0.138117671012842);
MyAnnotation *annotation = [[MyAnnotation alloc]initWithCoordinates:location title:@"MyTitle" subTitle:@"My Sub Title"];
[myMapView addAnnotation:annotation];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
在地图上添加一些不同颜色的锚点
通过mapView:viewForAnnotation:这个方法来返回一个MKPinAnnotationView实例对象,来进行操作。每一个动画都是添加到一个MKMapView实例化对象的视图上,然后加以显示的。这些视图一般称为动画视图。一个动画视图是一个MKAnnotationView类型的对象。也是UIView的子类。如果一个实现类的对象是一个地图的视图,并且实现了mapView:viewForAnnotation:这个方法,那么这个实现类将会返回一个MKAnnotationView的实例,然后你可以自己添加一个动画的视图效果,从而使他们在地图上得以显示。
MKPinAnnotationView
mapView:viewForAnnotation
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
MKAnnotationView *result = nil;
if([annotation isKindOfClass:[MyAnnotation class]] == NO){
return result;
}
if ([mapView isEqual:mapView] == NO) {
return result;
}
MyAnnotation *senderAnnotation = (MyAnnotation *)annotation;
NSString *pinReusableIdentifier = [MyAnnotation reusableIdentifierforPinColor:senderAnnotation.pinColor];
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[mapViewdequeueReusableAnnotationViewWithIdentifier:pinReusableIdentifier];
if(annotationView == nil){
annotationView = [[MKPinAnnotationView alloc]initWithAnnotation:senderAnnotationreuseIdentifier:pinReusableIdentifier];
[annotationView setCanShowCallout:YES];
}
annotationView.pinColor = senderAnnotation.pinColor;
result = annotationView;
return result;
}
在地图上添加自定义的锚点
通过UIImage 引入一个你自定义的图片,然后把它绑定到 MKAnnotationView的image这个属性上去,以一个锚点的形式返回到你的地图视图上。代码如下:
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#define REUSABLE_PIN_RED @"Red"
#define REUSABLE_PIN_GREEN @"Green"
#define REUSABLE_PIN_PURPLE @"Purple"
@interface MyAnnotation : NSObject<MKAnnotation>
@property(nonatomic,readonly)CLLocationCoordinate2D coordinate;
@property(nonatomic,copy,readonly)NSString *title;
@property(nonatomic,copy,readonly)NSString *subtitle;
@property(nonatomic,unsafe_unretained)MKPinAnnotationColor pinColor;
-(id)initWithCoordinates:(CLLocationCoordinate2D)paramCoordinates title:(NSString *)paramTitle subTitle:(NSString*)paramSubTitle;
+(NSString *)reusableIdentifierforPinColor:(MKPinAnnotationColor)paramColor;
@end
#import "MyAnnotation.h"
@interface MyAnnotation ()
@end
@implementation MyAnnotation
CLLocationCoordinate2D coordinate;
@synthesize coordinate,title,subtitle,pinColor;
-(id)initWithCoordinates:(CLLocationCoordinate2D)paramCoordinates title:(NSString *)paramTitle subTitle:(NSString*)paramSubTitle{
self = [super init];
if(self != nil){
coordinate = paramCoordinates;
title = paramTitle;
subtitle = paramSubTitle;
}
return (self);
}
+(NSString *)reusableIdentifierforPinColor:(MKPinAnnotationColor)paramColor{
NSString *result = nil;
switch (paramColor) {
case MKPinAnnotationColorRed:{
result = REUSABLE_PIN_RED;
break;
}
case MKPinAnnotationColorGreen:{
result = REUSABLE_PIN_GREEN;
break;
}
case MKPinAnnotationColorPurple:{
result = REUSABLE_PIN_PURPLE;
break;
}
}
return result;
}
@end
#import <UIKit/UIKit.h>
#import "MyAnnotation.h"
@interface MapViewController : UIViewController<MKMapViewDelegate>
@property(nonatomic,strong)MKMapView *myMapView;
@end
#import "MapViewController.h"
@interface MapViewController ()
@end
@implementation MapViewController
@synthesize myMapView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
myMapView = [[MKMapView alloc]initWithFrame:self.view.bounds];
myMapView.delegate = self;
myMapView.mapType = MKMapTypeStandard;
myMapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:myMapView];
CLLocationCoordinate2D location = CLLocationCoordinate2DMake(50.82191692907181, -0.138117671012842);
MyAnnotation *annotation = [[MyAnnotation alloc]initWithCoordinates:location title:@"MyTitle" subTitle:@"My Sub Title"];
[myMapView addAnnotation:annotation];
}
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
MKAnnotationView *result = nil;
if([annotation isKindOfClass:[MyAnnotation class]] == NO){
return result;
}
if([mapView isEqual:mapView] == NO){
return result;
}
MyAnnotation *senderAnnotation = (MyAnnotation *)annotation;
NSString *pinReusableIdentifier = [MyAnnotation reusableIdentifierforPinColor:senderAnnotation.pinColor];
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[mapViewdequeueReusableAnnotationViewWithIdentifier:pinReusableIdentifier];
if(annotationView == nil){
annotationView = [[MKPinAnnotationView alloc]initWithAnnotation:senderAnnotationreuseIdentifier:pinReusableIdentifier];
annotationView.canShowCallout = YES;
}
annotationView.pinColor = senderAnnotation.pinColor;
UIImage *pinImage = [UIImage imageNamed:@"BluePin.png"];
if (pinImage != pinImage) {
annotationView.image = pinImage;
}
result = annotationView;
return result;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
通过一组经纬度数据得到一个地点名称
通过一组经纬度数据得到一个实在的地理位置数据,我们通常称之为逆向地理编码。
创建一个CLGeocoder的实例对象,然后创建一个完整的块对象,这个对象必须要没有返回值,而且要接收两个参数。
一个NSArray类型的地点标记参数,这个参数将会用来保存你讲需要查询的地理位置。
一个NSError类型参数,这个参数将会返回一些地理位置编码信息是否正确的校验信息。
erverseGeocodeLocation:completionHandle 这个方法来进行反向地理位置编码。
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
@interface AddressViewController : UIViewController
@property(nonatomic,strong)CLGeocoder *myGeocoder;
@end
#import "AddressViewController.h"
@interface AddressViewController ()
@end
@implementation AddressViewController
@synthesize myGeocoder;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
CLLocation *location = [[CLLocation alloc]initWithLatitude:+38.4112810 longitude:-122.8409780f];
myGeocoder = [[CLGeocoder alloc]init];
[myGeocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error) {
if (error == nil && [placemarks count] > 0) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
NSLog(@"Country = %@",placemark.country);
NSLog(@"Postal Code = %@",placemark.postalCode);
NSLog(@"Locality = %@",placemark.locality);
}else if (error == nil && [placemarks count] == 0){
NSLog(@"No results were returned.");
}else if (error != nil){
NSLog(@"An error occurred = %@",error);
}
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
通过一个有意义的地址得到一组经纬度数据
通过一个地理名称得到一组经纬度数据
通过GLGeocoder 这个类的 geocodeAddressString:completionHandler 这个方法来实现
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
/*通过一个有意义的地址得到一组经纬度数据*/
@interface GetCodeViewController : UIViewController
@property(nonatomic,strong)CLGeocoder *myGeocoder;
@end
#import "GetCodeViewController.h"
@interface GetCodeViewController ()
@end
@implementation GetCodeViewController
@synthesize myGeocoder;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *oreillyAddress = @"1005 Gravenstein Highway North,Sebastopol,CA95472,USA";
myGeocoder = [[CLGeocoder alloc]init];
[myGeocoder geocodeAddressString:oreillyAddress completionHandler:^(NSArray *placemarks, NSError *error) {
if([placemarks count] > 0 && error == nil){
NSLog(@"Found %lu placemark(s).",(unsigned long)[placemarks count]);
CLPlacemark *firstPlacemark = [placemarks objectAtIndex:0];
NSLog(@"Longitude = %f",firstPlacemark.location.coordinate.longitude);
NSLog(@"Latitude = %f",firstPlacemark.location.coordinate.latitude);
}else if ([placemarks count] == 0 && error == nil){
NSLog(@"@Found no placemarks.");
}else if (error != nil){
NSLog(@"An error occurred = %@",error);
}
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end