iOS中有三个定位服务组件:
Wifi定位,通过查询一个Wifi路由器的地理位置的信息。比较省电,iPod touch和iPad也可以采用。
蜂窝基站定位,通过移动运用商基站定位。也适合有3G版本的iPod touch和iPad。
GPS卫星定位,通过3-4颗GPS定位位置定位,最为准确,但是耗电量大,不能遮挡。
Core Location
Core Location是iPhone、iPad等开发定位服务应用程序的框架。我们要在Xcode中添加“CoreLocation.framework”存在的框架。
主要使用的类是:CLLocationManager,通过CLLocationManager实现定位服务。
CoreLocation.framework
定位服务实例
项目WhereAmI:
WhereAmIViewController.h
#import <UIKit/UIKit.h> #import <CoreLocation/CoreLocation.h> @interface ViewController : UIViewController<CLLocationManagerDelegate> { CLLocationManager* locationManager; } @property (strong, nonatomic) CLLocationManager* locationManager; @property (retain, nonatomic) IBOutlet UILabel *longitudeText; @property (retain, nonatomic) IBOutlet UILabel *latituduText; @property (retain, nonatomic) IBOutlet UIActivityIndicatorView *activity; - (IBAction)findMe:(id)sender; - (IBAction)webMap:(id)sender; @end
CLLocationManagerDelegate是定位服务的委托,常用的位置变化回调方法是:
locationManager:didUpdateToLocation:fromLocation: locationManager:didFailWithError:
CLLocationManager 是定位服务管理类,通过它可以设置定位服务的参数、获取经纬度等。
m中加载方法
- (IBAction)findMe:(id)sender { self.locationManager = [[[CLLocationManager alloc] init] autorelease]; self.locationManager.delegate = self; self.locationManager.desiredAccuracy = kCLLocationAccuracyBest; self.locationManager.distanceFilter = 1000.0f; [self.locationManager startUpdatingLocation]; [activity startAnimating]; NSLog(@"start gps"); }
CLLocationManager 是的startUpdatingLocation方法启动所有定位硬件,对应的方法是stopUpdatingLocation,通过调用该方法关闭定位服务器更新,为了省电必须在不用的时候调用该方法关闭定位服务。
此外,我们还可以在这里设定定位服务的参数,包括:distanceFilter和desiredAccuracy。
distanceFilter,这个属性用来控制定位服务更新频率。单位是“米”。 desiredAccuracy,这个属性用来控制定位精度,精度
越高耗电量越大。
定位精度
desiredAccuracy精度参数可以iOS SDK通过常量实现:
kCLLocationAccuracyNearestTenMeters,10米
kCLLocationAccuracyHundredMeters ,100米
kCLLocationAccuracyKilometer ,1000米
kCLLocationAccuracyThreeKilometers,3000米
kCLLocationAccuracyBest ,最好的精度
kCLLocationAccuracyBestForNavigation,导航情况下最好精度,iOS 4 SDK新增加。一般要有外接电源时候才能使用。
委托方法用于实现位置的更新
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { latituduText.text = [NSString stringWithFormat:@"%3.5f",newLocation.coordinate.latitude]; longitudeText.text = [NSString stringWithFormat:@"%3.5f",newLocation.coordinate.longitude]; [activity stopAnimating]; [locationManager stopUpdatingLocation]; NSLog(@"location ok"); }
该委托方法不仅可以获得当前位置(newLocation),还可以获得上次的位置(oldLocation ),CLLocation 对象coordinate.latitude属性获得经度,coordinate.longitude属性获得纬度。
[NSString stringWithFormat:@"%3.5f”, newLocation.coordinate.latitude] 中的%3.5f是输出整数部分是3位,小数部分是5位的浮点数。
11.2 iOS地图
iOS应用程序中使用Map Kit API开发地图应用程序。
其核心是MKMapView类使用。
多数情况下地图会与定位服务结合使用。
地图开发一般过程
添加MapKit类库
MapKit.framework
MapMeViewController.h
#import <UIKit/UIKit.h> #import <MapKit/MapKit.h> #import <CoreLocation/CoreLocation.h> #import "MapLocation.h" @interface ViewController : UIViewController<CLLocationManagerDelegate, MKReverseGeocoderDelegate, MKMapViewDelegate> { } @property (retain, nonatomic) IBOutlet MKMapView *mapView; @property (retain, nonatomic) IBOutlet UIActivityIndicatorView *activity; - (IBAction)findMe:(id)sender; @end
CLLocationManagerDelegate是定位服务委托。
MKMapViewDelegate是地图视图委托,主要方法:
-mapView:viewForAnnotation:
-mapViewDidFailLoadingMap:withError:
MKReverseGeocoderDelegate是给地理坐标获得标志点信息的委托,用于地理信息编码(即:从坐标获得地点获得信息),主要委托方法:
– reverseGeocoder:didFindPlacemark:
– reverseGeocoder:didFailWithError:
m文件中的视图加载和卸载
- (void)viewDidLoad { [super viewDidLoad]; mapView.mapType = MKMapTypeStandard; //mapView.mapType = MKMapTypeSatellite; //mapView.mapType = MKMapTypeHybrid; mapView.delegate = self; }
mapView.mapType = MKMapTypeStandard;是指定地图的类型,iOS提供了三种风格的地图:
MKMapTypeStandard标准地图模式
MKMapTypeSatellite卫星地图模式
MKMapTypeHybrid具有街道等信息的卫星地图模式
mapView.delegate = self;是将委托对象指定为自身。
按钮事件
- (IBAction)findMe:(id)sender { CLLocationManager *lm = [[CLLocationManager alloc] init]; lm.delegate = self; lm.desiredAccuracy = kCLLocationAccuracyBest; [lm startUpdatingLocation]; activity.hidden = NO; [activity startAnimating]; }
点击按钮时候通过定位服务获取当前位置信息。
通过lm.delegate = self;是将委托对象指定为自身。
因此,点击事件发生时候将会回调CLLocationManagerDelegate委托的
-locationManager:didUpdateToLocation:fromLocation:方法。
回调位置更新方法
#pragma mark CLLocationManagerDelegate Methods - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 2000, 2000); //[mapView setRegion:viewRegion animated:YES]; MKCoordinateRegion adjustedRegion = [mapView regionThatFits:viewRegion]; [mapView setRegion:adjustedRegion animated:YES]; manager.delegate = nil; [manager stopUpdatingLocation]; MKReverseGeocoder *geocoder = [[MKReverseGeocoder alloc] initWithCoordinate:newLocation.coordinate]; geocoder.delegate = self; [geocoder start]; }
MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 2000, 2000); 该函数能够创建一个MKCoordinateRegion结构体,第一个参数是一个CLLocationCoordinate2D结构指定了目标区域的中心点,第二个是目标区域南北的跨度单位是米,第三个是目标区域东西的跨度单位是米。后两个参数的调整会影响地图缩放。
[[MKReverseGeocoder alloc] initWithCoordinate:newLocation.coordinate]; 创建地理编码对象geocoder,通过该对象可以把坐标转换成为地理信息的描述。
geocoder.delegate = self;指定编码的处理是自身对象。
[geocoder start];开始编码处理。
MKReverseGeocoderDelegate
是地理编码委托对象,该委托的方法:
成功时候调用-reverseGeocoder:didFindPlacemark:
失败时候调用-reverseGeocoder:didFailWithError:
成功编码回调方法
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark { MapLocation *annotation = [[MapLocation alloc] init]; annotation.streetAddress = placemark.thoroughfare; annotation.city = placemark.locality; annotation.state = placemark.administrativeArea; annotation.zip = placemark.postalCode; annotation.coordinate = geocoder.coordinate; [mapView addAnnotation:annotation]; [annotation release]; geocoder.delegate = nil; [geocoder autorelease]; [activity stopAnimating]; activity.hidden = YES; }
成功编码后需要在该方法中创建标注对象(MapLocation)。MapLocation 是我们自定义的实现MKAnnotation协议标注对象。 该方法的placemark是MKPlacemark获得很多地理信息,详细见下表。
[mapView addAnnotation:annotation]; 为地图添加标注,该方法将会触发mapView:viewForAnnotation:方法回调。
MKPlacemark类属性
addressDictionary 地址信息的dictionary
thoroughfare 指定街道级别信息
subThoroughfare 指定街道级别的附加信息
locality 指定城市信息
subLocality 指定城市信息附加信息
administrativeArea 行政区域
subAdministrativeArea 行政区域附加信息
country 国家信息
countryCode 国家代号
postalCode 邮政编码
失败编码回调方法
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"地理解码错误息" message:@"地理代码不能识别" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil]; [alert show]; [alert release]; geocoder.delegate = nil; [geocoder autorelease]; [activity stopAnimating]; }
MKMapViewDelegate
是地图视图委托对象,本例子我们使用的方法:
- mapView:viewForAnnotation:为地图设置标注时候回调方法。
-mapViewDidFailLoadingMap:withError:地图加载错误时候回调方法。
地图标注回调方法
#pragma mark Map View Delegate Methods - (MKAnnotationView *) mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>) annotation { MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"PIN_ANNOTATION"]; if(annotationView == nil) { annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"PIN_ANNOTATION"] autorelease]; } annotationView.canShowCallout = YES; annotationView.pinColor = MKPinAnnotationColorRed; annotationView.animatesDrop = YES; annotationView.highlighted = YES; annotationView.draggable = YES; return annotationView; }
与表格视图单元格处理类似,地图标注对象由于会很多,因此需要重复利用,通过
dequeueReusableAnnotationViewWithIdentifier方法可以查找可重复利用的标注对象,以达到节省内存的目的。
annotationView.canShowCallout = YES;指定标注上的插图,点击图钉有气泡显示。
annotationView.pinColor 设置图钉的颜色。
annotationView.animatesDrop动画效果。
地图加载失败回调方法
- (void)mapViewDidFailLoadingMap:(MKMapView *)theMapView withError:(NSError *)error { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"地图加载错误" message:[error localizedDescription] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil]; [alert show]; [alert release]; }
自定义地图标注对象
#import <Foundation/Foundation.h> #import <MapKit/MapKit.h> @interface MapLocation : NSObject <MKAnnotation, NSCoding> { NSString *streetAddress; NSString *city; NSString *state; NSString *zip; CLLocationCoordinate2D coordinate; } @property (nonatomic, copy) NSString *streetAddress; @property (nonatomic, copy) NSString *city; @property (nonatomic, copy) NSString *state; @property (nonatomic, copy) NSString *zip; @property (nonatomic, readwrite) CLLocationCoordinate2D coordinate; @end
作为地图标注对象实现MKAnnotation协议是必须的,只有实现该协议才能使该类成为标注类。实现NSCoding协议是可选的,实现该协议可以使标注对象能够复制。 里面的属性有哪些要看你自己的需要。
MapLocation.m
- (NSString *)title { return @"您的位置!"; } - (NSString *)subtitle { NSMutableString *ret = [NSMutableString string]; if (streetAddress) [ret appendString:streetAddress]; if (streetAddress && (city || state || zip)) [ret appendString:@" • "]; if (city) [ret appendString:city]; if (city && state) [ret appendString:@", "]; if (state) [ret appendString:state]; if (zip) [ret appendFormat:@", %@", zip]; return ret; }
title 和subtitle 是MKAnnotation协议要求实现的方法。
MapLocation.m
#pragma mark - - (void)dealloc { [streetAddress release]; [city release]; [state release]; [zip release]; [super dealloc]; } #pragma mark - #pragma mark NSCoding Methods - (void) encodeWithCoder: (NSCoder *)encoder { [encoder encodeObject: [self streetAddress] forKey: @"streetAddress"]; [encoder encodeObject: [self city] forKey: @"city"]; [encoder encodeObject: [self state] forKey: @"state"]; [encoder encodeObject: [self zip] forKey: @"zip"]; } - (id) initWithCoder: (NSCoder *)decoder { if (self = [super init]) { [self setStreetAddress: [decoder decodeObjectForKey: @"streetAddress"]]; [self setCity: [decoder decodeObjectForKey: @"city"]]; [self setState: [decoder decodeObjectForKey: @"state"]]; [self setZip: [decoder decodeObjectForKey: @"zip"]]; } return self; }
encodeWithCoder:和initWithCoder:是NSCoding协议要求实现方法。
11.3 Web地图
在iOS中我们还可以使用Web地图。
- (IBAction)webMap:(id)sender { CLLocation *lastLocation = [locationManager location]; if(!lastLocation) { UIAlertView *alert; alert = [[UIAlertView alloc] initWithTitle:@"系统错误" message:@"还没有接收到数据!" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil]; [alert show]; [alert release]; return; } NSString *urlString = [NSString stringWithFormat: @"http://maps.google.com/maps?q=Here+I+Am!@%f,%f", lastLocation.coordinate.latitude, lastLocation.coordinate.longitude]; NSURL *url = [NSURL URLWithString:urlString]; [[UIApplication sharedApplication] openURL:url]; }
与iOS6的苹果didUpdateLocations代替didUpdateToLocation的释放。任何人都可以解释如何didUpdateLocations?
本文地址 :CodeGo.net/507856/
-------------------------------------------------------------------------------------------------------------------------
1. 我以下的委托,以获得最后一个位置?
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
上述委托弃用的iOS 6。现在,下面应该
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
为了获得最后的位置,只需获取数组的最后一个对象:
[locations lastObject]
换句话说,[locations lastObject](新代表)等于newLocation(老代表)。
2. 它给你的对象数组来访问最后一个位置你
[locations lastObject]
由此
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
3. 这里没有其他的答案中解释了为什么有一个位置阵列,以及如何将新didUpdateLocations:提供的数组。 贬低的目的locationManager:didUpdateToLocation:fromLocation:和发送位置一个NSArray,而不是在后台运行时降低功耗。 与iPhone 5开始时,GPS芯片具有存储位置的一段,然后传送在一次阵列中的他们所有的能力。这被称为延迟的位置更新。这允许主CPU进入睡眠状态,而在背景中较长的时间。的iOS不具备启动主CPU的每个位置更新时,CPU可以睡,而GPS芯片集的位置。 您可以检查这个deferredLocationUpdatesAvailable方法。如果可用,您可以启用allowDeferredLocationUpdatesUntilTraveled:timeout:方法。条件适用,看到这个答案的细节。
4. 如果你支持的iOS 5和6,你应该叫
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations,
从旧
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
功能,通过建立的位置的阵列。
本文标题 :didUpdateLocations代替didUpdateToLocation
本文地址 :CodeGo.net/507856/
继续浏览 :Maven的javadoc中,插件和故障安全maven的插件缺失时生成JBoss Seam的例子
您可以会感兴趣的文章:
1. EmberJS嵌套视图和控制器
2. listview与复选框,单选按钮,TextView的和按钮无法正常工作在Android
3. 使用自定义控制台为Visual Studio控制台应用程序调试
4. 升级到4.5的Xcode后的iOS 5 SDK中消失了
5. 从基本形式访问连接字符串会导致错误的设计师
6. 在小区的空值处理
7. 无法显示在欲望的格式报告[关闭]
8. Mysql的动态触发创建存储过程
9. NoClassDefFoundError的:android/support/v4/content/LocalBroadcastManager
10. 如何正确地安装mysqlconnecter java吗?
11. 可以选择的样式元素,以便选定的选项样式显示下拉列表时,'封闭'?
12. 在JavaEE的6子进程执行
13. R和矩阵1的行
14. 旋转和尺度不变性的模板匹配在OpenCV的[复制]
15. 在列表中创建使用数据填充的等高线图
16. 安卓+PhoneGap的拦截的URL(相当于iOS的shouldStartLoadWithRequest的)
17. 泛型类与约束访问问题
18. 什么是法律约束缓存事件意思?
19. SBT:添加依赖scalatest库。在哪里?
20. 什么是PK和FK我应该分配给我的桌子吗?
IOS定位核心与地图
Core Location以及Map框架包通常能给我们的应用程序添加定位和地图相关的服务。Core Location框架包通常是使用硬件设备来进行定位服务的,Map框架包通常能够使你的应用程序做一些地图展示与交互的相关功能。地图的定位服务一般需要依赖设备的硬件组成部分。如果有定位的硬件设备,那么肯定是可以利用地图框架包来进行地图的一些相关的操作。
为了能够在项目中使用到位置服务以及地图展示的相关功能,你必须要导入Core Location 和Map这两个框架包。如果你不知道怎么做,那么请参照如下步骤。
1.点击你的项目工程图标文件。
2.然后选择target选项,如图1所示。
3.然后选择Build Phase模块栏。
4.然后点开Link Binary With Libraries栏目,在点击+号按钮。
图1 添加相关的框架包
5.添加MapKit.framework和CoreLocation.framework这两个库
6.在使用地图和定位的地方,导入:
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
MKMapView是UIView的子类,所以可以像一个普通的View一样添加到ViewController的View当中。
以下是相关的代码
ViewController.h
-
#import <UIKit/UIKit.h>
-
#import <CoreLocation/CoreLocation.h>
-
#import <MapKit/MapKit.h>
-
#import "MyAnnotation.h"
-
-
@interface ViewController : UIViewController <MKMapViewDelegate,CLLocationManagerDelegate>
-
-
// MapView
-
@property (nonatomic,strong) MKMapView *myMapView;// 地图控件
-
// LocationManager
-
@property (nonatomic,strong) CLLocationManager *myLocationManager;// 位置管理器
-
@property (nonatomic,strong) CLGeocoder *myGeoCoder ;// 地理位置和真实地址转换
-
@end
ViewController.m
-
#import "ViewController.h"
- #import "MKMapView+ZoomLevel.h"
-
- @interface ViewController ()
-
- @end
-
- @implementation ViewController
-
- @synthesize myMapView;
-
@synthesize myLocationManager;
- @synthesize myGeoCoder;
-
- (void)viewDidLoad
- {
-
[super viewDidLoad];
-
// Do any additional setup after loading the view, typically from a nib.
-
// 设置根View的背景颜色
- self.view.backgroundColor = [UIColor colorWithRed:0x33 / 255.0f green:0x66 / 255.0f blue:0x99 / 255.0f alpha:0xFF / 255.0f];
-
// 初始化MapView并且设置MapView显示的边界
- self.myMapView = [[MKMapView alloc]initWithFrame:self.view.bounds];
-
// self.myMapView.mapType = MKMapTypeSatellite;
- // self.myMapView.mapType = MKMapTypeHybrid;
-
self.myMapView.mapType = MKMapTypeStandard;
- self.myMapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
-
self.myMapView.delegate = self;
-
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(40.034122, 116.289574);
- MyAnnotation *annotation = [[MyAnnotation alloc]initWithCoordinate:coordinate title:@"我的位置" subTitle:@"这里就是寡人的位置,嘿嘿!"];
-
annotation.pinColor = MKPinAnnotationColorPurple;
-
[self.myMapView addAnnotation:annotation];
-
- [self.myMapView setShowsUserLocation:YES];
-
[self.myMapView setCenterCoordinate:coordinate zoomLevel:15 animated:YES];
-
[self.view addSubview:myMapView];
-
- if([CLLocationManager locationServicesEnabled]){
-
self.myLocationManager = [[CLLocationManager alloc]init];
- self.myLocationManager.delegate = self;
-
// // 提示用户是否允许当前应用使用地理位置,已过时,在Info.plist中使用NSLocationUsageDescription键值替换
- // self.myLocationManager.purpose = @"提示用户是否允许当前应用使用位置,已过时";
-
[self.myLocationManager startUpdatingLocation];
- }else{
-
NSLog(@">>>>>>>>>> 位置服务不可用 <<<<<<<<<<<<");
- UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"您的位置服务当前不可用,请打开位置服务后重试" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
-
[alertView show];
- }
-
-
CLLocation *location = [[CLLocation alloc]initWithLatitude:40.034122 longitude:116.289574];
-
self.myGeoCoder = [[CLGeocoder alloc]init];
- [self.myGeoCoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks,NSError *error){
-
if(error == nil && [placemarks count] > 0){
- CLPlacemark *pm = [placemarks objectAtIndex:0];
-
NSLog(@"国家:%@" ,pm.country);
- NSLog(@"邮编:%@",pm.postalCode);
-
NSLog(@"Locality:%@",pm.locality);
- }else if(error == nil && [placemarks count] == 0){
-
NSLog(@"没有地址返回");
- }else if(error != nil){
-
NSLog(@"出错了:%@",error);
- }
-
}];
-
[self.myGeoCoder geocodeAddressString:@"中国北京市海淀区花园东路10号高德大厦" completionHandler:^(NSArray *placemarks,NSError *error){
- if(nil == error && [placemarks count] > 0){
-
NSLog(@"placemarks count:%i",[placemarks count]);
- CLPlacemark *pm = [placemarks objectAtIndex:0];
-
NSLog(@"longitude=%f",pm.location.coordinate.longitude);
- NSLog(@"latitude=%f",pm.location.coordinate.latitude);
-
}else if([placemarks count] == 0 && error == nil){
- NSLog(@"找不到给定地址的经纬度");
-
}else if(nil != nil){
- NSLog(@"发生了错误:%@",error);
-
}
- }];
-
-
-
- }
-
- - (void)didReceiveMemoryWarning
-
{
- [super didReceiveMemoryWarning];
-
// Dispose of any resources that can be recreated.
-
}
- -(void)viewDidUnload
-
{
- [super viewDidUnload];
-
self.myMapView = nil;
- [self.myLocationManager stopUpdatingLocation];
-
self.myLocationManager = nil;
- }
-
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
- {
-
return YES;
- }
-
-
/*******************************************************************************************/
- /*******************************************************************************************/
-
/*************************** MapView的Delegate的方法,全部都是Option的 *************************/
- /*******************************************************************************************/
-
/*******************************************************************************************/
- /*******************************************************************************************/
-
- - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
-
NSLog(@"mapView:regionWillChangeAnimated:方法被调用");
- }
-
// 用户的地理位置发生改变的时候调用
- - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
-
NSLog(@"mapView:regionDidChangeAnimated:方法被调用");
- }
-
// 当地图界面将要加载的时候将会调用这个方法
- - (void)mapViewWillStartLoadingMap:(MKMapView *)mapView{
-
NSLog(@"mapViewWillStartLoadingMap:方法被调用");
- }
-
// 当地图界面加载完成的时候将要调用这个方法
- - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView{
-
NSLog(@"mapViewDidFinishLoadingMap:方法被调用");
- }
-
// 当地图界面加载失败的时候调用这个方法
- - (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error{
-
NSLog(@"mapViewDidFailLoadingMap:withError:方法被调用,error is:%@" , [error description]);
- }
-
// 添加到地图的Annotation
- // mapView:viewForAnnotation: provides the view for each annotation.
-
// This method may be called for all or some of the added annotations.
- // For MapKit provided annotations (eg. MKUserLocation) return nil to use the MapKit provided annotation view.
-
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
- {
-
MKAnnotationView *view = nil;
- if([annotation isKindOfClass:[MyAnnotation class]] == NO){
-
return view;
- }
-
if([mapView isEqual:self.myMapView] == NO){
- return view;
-
}
-
MyAnnotation *senderAnnotation = (MyAnnotation*)annotation;
- NSString *pinReusableIdentifier = [MyAnnotation reusableIdentifierForPinColor:senderAnnotation.pinColor];
-
MKPinAnnotationView *annotationView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:pinReusableIdentifier];
- if(annotationView == nil){
-
annotationView = [[MKPinAnnotationView alloc]initWithAnnotation:senderAnnotation reuseIdentifier:pinReusableIdentifier];
- [annotationView setCanShowCallout:YES];
-
}
- annotationView.pinColor = senderAnnotation.pinColor;
-
-
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- NSString *documentPath = [paths objectAtIndex:0];
-
-
NSString *cachePath = [documentPath stringByAppendingString:@"/images"];
- NSString *cacheFile = [cachePath stringByAppendingString:@"icon.image"];
-
- if([[NSFileManager defaultManager]fileExistsAtPath:cacheFile]){
-
UIImage *image = [UIImage imageWithContentsOfFile:cacheFile];
- if(image != nil){
-
annotationView.image = image;
- NSLog(@"通过本地设置图片");
-
}else{
- [self setAnnotionImageByUrl:annotationView cacheFile:cacheFile];
-
}
- }else{
-
[self setAnnotionImageByUrl:annotationView cacheFile:cacheFile];
- }
-
view = annotationView;
-
return view;
- }
-
- -(void) setAnnotionImageByUrl:(MKPinAnnotationView *)annotationView cacheFile:(NSString *) cacheFile{
-
NSLog(@"通过网络设置文件");
- dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
-
dispatch_async(queue, ^{
-
-
NSURL *url = [NSURL URLWithString:@"http://www.baidu.com/img/duanwulogo_94a0060bda0885d1c2320ca0d7d7c342.gif"];
- NSData *data = [NSData dataWithContentsOfURL:url];
-
- if(data != nil){
-
- [data writeToFile:cacheFile atomically:YES];
-
- UIImage *image = [UIImage imageWithData:data];
-
dispatch_queue_t mainQueue = dispatch_get_main_queue();
- dispatch_async(mainQueue, ^{
-
if(image != nil){
- annotationView.image = image;
-
}
- });
-
}
- });
-
- }
-
- /**
-
- // mapView:didAddAnnotationViews: is called after the annotation views have been added and positioned in the map.
-
// The delegate can implement this method to animate the adding of the annotations views.
- // Use the current positions of the annotation views as the destinations of the animation.
-
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views;
-
// mapView:annotationView:calloutAccessoryControlTapped: is called when the user taps on left & right callout accessory UIControls.
- - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control;
-
- - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view NS_AVAILABLE(NA, 4_0);
-
- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view NS_AVAILABLE(NA, 4_0);
-
- (void)mapViewWillStartLocatingUser:(MKMapView *)mapView NS_AVAILABLE(NA, 4_0);
- - (void)mapViewDidStopLocatingUser:(MKMapView *)mapView NS_AVAILABLE(NA, 4_0);
-
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation NS_AVAILABLE(NA, 4_0);
- - (void)mapView:(MKMapView *)mapView didFailToLocateUserWithError:(NSError *)error NS_AVAILABLE(NA, 4_0);
-
- - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view didChangeDragState:(MKAnnotationViewDragState)newState
-
fromOldState:(MKAnnotationViewDragState)oldState NS_AVAILABLE(NA, 4_0);
-
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay NS_AVAILABLE(NA, 4_0);
-
// Called after the provided overlay views have been added and positioned in the map.
- - (void)mapView:(MKMapView *)mapView didAddOverlayViews:(NSArray *)overlayViews NS_AVAILABLE(NA, 4_0);
-
- - (void)mapView:(MKMapView *)mapView didChangeUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated NS_AVAILABLE(NA, 5_0);
-
*/
-
-
- /*******************************************************************************************/
-
/*******************************************************************************************/
- /*************************** 位置相关 *************************/
-
/*******************************************************************************************/
- /*******************************************************************************************/
-
/*******************************************************************************************/
-
-(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
-
{
-
NSLog(@"获得位置失败");
- }
-
- @end
MKMapView+ZoomLevel.h
-
#import <MapKit/MapKit.h>
-
@interface MKMapView (ZoomLevel)
- - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
-
zoomLevel:(NSUInteger)zoomLevel
- animated:(BOOL)animated;
-
@end
MKMapView+ZoomLevel.m
-
#import "MKMapView+ZoomLevel.h"
-
@implementation MKMapView (ZoomLevel)
- #define MERCATOR_OFFSET 268435456
-
#define MERCATOR_RADIUS 85445659.44705395
-
#pragma mark -
- #pragma mark Map conversion methods
-
- - (double)longitudeToPixelSpaceX:(double)longitude
-
{
- return round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * M_PI / 180.0);
-
}
-
- (double)latitudeToPixelSpaceY:(double)latitude
- {
-
return round(MERCATOR_OFFSET - MERCATOR_RADIUS * logf((1 + sinf(latitude * M_PI / 180.0)) / (1 - sinf(latitude * M_PI / 180.0))) / 2.0);
- }
-
- - (double)pixelSpaceXToLongitude:(double)pixelX
-
{
- return ((round(pixelX) - MERCATOR_OFFSET) / MERCATOR_RADIUS) * 180.0 / M_PI;
-
}
-
- (double)pixelSpaceYToLatitude:(double)pixelY
- {
-
return (M_PI / 2.0 - 2.0 * atan(exp((round(pixelY) - MERCATOR_OFFSET) / MERCATOR_RADIUS))) * 180.0 / M_PI;
- }
-
- #pragma mark -
-
#pragma mark Helper methods
-
- (MKCoordinateSpan)coordinateSpanWithMapView:(MKMapView *)mapView
- centerCoordinate:(CLLocationCoordinate2D)centerCoordinate
-
andZoomLevel:(NSUInteger)zoomLevel
- {
-
// convert center coordiate to pixel space
- double centerPixelX = [self longitudeToPixelSpaceX:centerCoordinate.longitude];
-
double centerPixelY = [self latitudeToPixelSpaceY:centerCoordinate.latitude];
-
// determine the scale value from the zoom level
- NSInteger zoomExponent = 20 - zoomLevel;
-
double zoomScale = pow(2, zoomExponent);
-
// scale the map's size in pixel space
- CGSize mapSizeInPixels = mapView.bounds.size;
-
double scaledMapWidth = mapSizeInPixels.width * zoomScale;
- double scaledMapHeight = mapSizeInPixels.height * zoomScale;
-
-
// figure out the position of the top-left pixel
-
double topLeftPixelX = centerPixelX - (scaledMapWidth / 2);
- double topLeftPixelY = centerPixelY - (scaledMapHeight / 2);
-
-
// find delta between left and right longitudes
-
CLLocationDegrees minLng = [self pixelSpaceXToLongitude:topLeftPixelX];
- CLLocationDegrees maxLng = [self pixelSpaceXToLongitude:topLeftPixelX + scaledMapWidth];
-
CLLocationDegrees longitudeDelta = maxLng - minLng;
-
// find delta between top and bottom latitudes
- CLLocationDegrees minLat = [self pixelSpaceYToLatitude:topLeftPixelY];
-
CLLocationDegrees maxLat = [self pixelSpaceYToLatitude:topLeftPixelY + scaledMapHeight];
- CLLocationDegrees latitudeDelta = -1 * (maxLat - minLat);
-
-
// create and return the lat/lng span
-
MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
- return span;
-
}
-
#pragma mark -
- #pragma mark Public methods
-
- - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
-
zoomLevel:(NSUInteger)zoomLevel
- animated:(BOOL)animated
-
{
-
// clamp large numbers to 28
-
zoomLevel = MIN(zoomLevel, 28);
-
// use the zoom level to compute the region
- MKCoordinateSpan span = [self coordinateSpanWithMapView:self centerCoordinate:centerCoordinate andZoomLevel:zoomLevel];
-
MKCoordinateRegion region = MKCoordinateRegionMake(centerCoordinate, span);
-
// set the region like normal
- [self setRegion:region animated:animated];
-
}
-
- @end
MyAnnotation.h
-
#import <Foundation/Foundation.h>
- #import <CoreLocation/CoreLocation.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, readonly, copy) NSString *title;
-
@property (nonatomic, readonly, copy) NSString *subtitle;
-
@property (nonatomic,unsafe_unretained) MKPinAnnotationColor pinColor;
-
-(id) initWithCoordinate:(CLLocationCoordinate2D) coordinate
- title:(NSString*) paramTitle
-
subTitle:(NSString*) paramSubTitle;
- // 得到颜色
-
+(NSString *) reusableIdentifierForPinColor:(MKPinAnnotationColor) paramColor;
-
@end
MyAnnotation.m
-
#import "MyAnnotation.h"
-
@implementation MyAnnotation
-
@synthesize coordinate,title,subtitle,pinColor;
-
-(id) initWithCoordinate
- :(CLLocationCoordinate2D) paramCoordinate title:(NSString *)paramTitle subTitle:(NSString *)paramSubTitle
-
{
- self = [super init];
-
if(self != nil){
- coordinate = paramCoordinate;
-
title = paramTitle;
- subtitle = paramSubTitle;
-
pinColor = MKPinAnnotationColorGreen;
- }
-
- 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;
-
}
- return result;
-
}
-
@end
注意,在使用用户的位置的时候,系统会弹出是否允许应用使用位置的对话框,这个对话框中的提示文字,可以自己进行定义
在系统版本是6.0(包括6.0)以上的时候,在Info.plist文件中进行定义
<key>NSLocationUsageDescription</key>
<string>是否可以使用位置?如果需要使用本应用,是必须的!</string>
在6.0以下,这样进行定义
- // // 提示用户是否允许当前应用使用地理位置,已过时,在Info.plist中使用NSLocationUsageDescription键值替换
- // self.myLocationManager.purpose = @"提示用户是否允许当前应用使用位置,已过时";