地图与定位

11.1 iOS定位服务

11.2 iOS地图

11.3 Web地图

1 iOS定位服务

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

  1. #import <UIKit/UIKit.h>
  2. #import <CoreLocation/CoreLocation.h>
  3.  
  4. @interface ViewController : UIViewController<CLLocationManagerDelegate> {
  5. CLLocationManager* locationManager;
  6. }
  7.  
  8. @property (strong, nonatomic) CLLocationManager* locationManager;
  9. @property (retain, nonatomic) IBOutlet UILabel *longitudeText;
  10. @property (retain, nonatomic) IBOutlet UILabel *latituduText;
  11. @property (retain, nonatomic) IBOutlet UIActivityIndicatorView *activity;
  12. - (IBAction)findMe:(id)sender;
  13. - (IBAction)webMap:(id)sender;
  14.  
  15. @end

CLLocationManagerDelegate是定位服务的委托,常用的位置变化回调方法是:

locationManager:didUpdateToLocation:fromLocation: locationManager:didFailWithError:

CLLocationManager 是定位服务管理类,通过它可以设置定位服务的参数、获取经纬度等。

m中加载方法

  1. - (IBAction)findMe:(id)sender {
  2. self.locationManager = [[[CLLocationManager alloc] init] autorelease];
  3. self.locationManager.delegate = self;
  4. self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
  5. self.locationManager.distanceFilter = 1000.0f;
  6. [self.locationManager startUpdatingLocation];
  7. [activity startAnimating];
  8. NSLog(@"start gps");
  9. }

CLLocationManager 是的startUpdatingLocation方法启动所有定位硬件,对应的方法是stopUpdatingLocation,通过调用该方法关闭定位服务器更新,为了省电必须在不用的时候调用该方法关闭定位服务。

此外,我们还可以在这里设定定位服务的参数,包括:distanceFilter和desiredAccuracy。

distanceFilter,这个属性用来控制定位服务更新频率。单位是“米”。 desiredAccuracy,这个属性用来控制定位精度,精度

越高耗电量越大。

定位精度 

desiredAccuracy精度参数可以iOS SDK通过常量实现:

kCLLocationAccuracyNearestTenMeters,10米

kCLLocationAccuracyHundredMeters ,100米

kCLLocationAccuracyKilometer ,1000米

kCLLocationAccuracyThreeKilometers,3000米

kCLLocationAccuracyBest ,最好的精度

kCLLocationAccuracyBestForNavigation,导航情况下最好精度,iOS 4 SDK新增加。一般要有外接电源时候才能使用。

委托方法用于实现位置的更新

  1. -(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
  2. latituduText.text = [NSString stringWithFormat:@"%3.5f",newLocation.coordinate.latitude];
  3. longitudeText.text = [NSString stringWithFormat:@"%3.5f",newLocation.coordinate.longitude];
  4. [activity stopAnimating];
  5. [locationManager stopUpdatingLocation];
  6. NSLog(@"location ok");
  7. }

该委托方法不仅可以获得当前位置(newLocation),还可以获得上次的位置(oldLocation ),CLLocation 对象coordinate.latitude属性获得经度,coordinate.longitude属性获得纬度。

[NSString stringWithFormat:@"%3.5f”, newLocation.coordinate.latitude]  中的%3.5f是输出整数部分是3位,小数部分是5位的浮点数。

2 iOS地图

iOS应用程序中使用Map Kit API开发地图应用程序。

其核心是MKMapView类使用。

多数情况下地图会与定位服务结合使用。

地图开发一般过程

添加MapKit类库

MapKit.framework

MapMeViewController.h

  1. #import <UIKit/UIKit.h>
  2. #import <MapKit/MapKit.h>
  3. #import <CoreLocation/CoreLocation.h>
  4. #import "MapLocation.h"
  5.  
  6. @interface ViewController : UIViewController<CLLocationManagerDelegate, MKReverseGeocoderDelegate, MKMapViewDelegate> {
  7.  
  8. }
  9.  
  10. @property (retain, nonatomic) IBOutlet MKMapView *mapView;
  11. @property (retain, nonatomic) IBOutlet UIActivityIndicatorView *activity;
  12. - (IBAction)findMe:(id)sender;
  13. @end

CLLocationManagerDelegate是定位服务委托。

MKMapViewDelegate是地图视图委托,主要方法:

-mapView:viewForAnnotation:

-mapViewDidFailLoadingMap:withError:

MKReverseGeocoderDelegate是给地理坐标获得标志点信息的委托,用于地理信息编码(即:从坐标获得地点获得信息),主要委托方法:

– reverseGeocoder:didFindPlacemark:

– reverseGeocoder:didFailWithError:

m文件中的视图加载和卸载

  1. - (void)viewDidLoad {
  2. [super viewDidLoad];
  3. mapView.mapType = MKMapTypeStandard;
  4. //mapView.mapType = MKMapTypeSatellite;
  5. //mapView.mapType = MKMapTypeHybrid;
  6. mapView.delegate = self;
  7. }

mapView.mapType = MKMapTypeStandard;是指定地图的类型,iOS提供了三种风格的地图:

MKMapTypeStandard标准地图模式

MKMapTypeSatellite卫星地图模式

MKMapTypeHybrid具有街道等信息的卫星地图模式

mapView.delegate = self;是将委托对象指定为自身。

按钮事件

  1. - (IBAction)findMe:(id)sender {
  2. CLLocationManager *lm = [[CLLocationManager alloc] init];
  3. lm.delegate = self;
  4. lm.desiredAccuracy = kCLLocationAccuracyBest;
  5. [lm startUpdatingLocation];
  6.  
  7. activity.hidden = NO;
  8. [activity startAnimating];
  9. }

点击按钮时候通过定位服务获取当前位置信息。

通过lm.delegate = self;是将委托对象指定为自身。

因此,点击事件发生时候将会回调CLLocationManagerDelegate委托的

-locationManager:didUpdateToLocation:fromLocation:方法。

回调位置更新方法

  1. #pragma mark CLLocationManagerDelegate Methods
  2. - (void)locationManager:(CLLocationManager *)manager
  3. didUpdateToLocation:(CLLocation *)newLocation
  4. fromLocation:(CLLocation *)oldLocation {
  5.  
  6. MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 2000, 2000);
  7. //[mapView setRegion:viewRegion animated:YES];
  8. MKCoordinateRegion adjustedRegion = [mapView regionThatFits:viewRegion];
  9. [mapView setRegion:adjustedRegion animated:YES];
  10.  
  11. manager.delegate = nil;
  12. [manager stopUpdatingLocation];
  13.  
  14. MKReverseGeocoder *geocoder = [[MKReverseGeocoder alloc] initWithCoordinate:newLocation.coordinate];
  15. geocoder.delegate = self;
  16. [geocoder start];
  17. }

MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 2000, 2000); 该函数能够创建一个MKCoordinateRegion结构体,第一个参数是一个CLLocationCoordinate2D结构指定了目标区域的中 心点,第二个是目标区域南北的跨度单位是米,第三个是目标区域东西的跨度单位是米。后两个参数的调整会影响地图缩放。

[[MKReverseGeocoder alloc] initWithCoordinate:newLocation.coordinate]; 创建地理编码对象geocoder,通过该对象可以把坐标转换成为地理信息的描述。

geocoder.delegate = self;指定编码的处理是自身对象。

[geocoder start];开始编码处理。

MKReverseGeocoderDelegate

是地理编码委托对象,该委托的方法:

成功时候调用-reverseGeocoder:didFindPlacemark:

失败时候调用-reverseGeocoder:didFailWithError:

成功编码回调方法

  1. - (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark {
  2.  
  3. MapLocation *annotation = [[MapLocation alloc] init];
  4. annotation.streetAddress = placemark.thoroughfare;
  5. annotation.city = placemark.locality;
  6. annotation.state = placemark.administrativeArea;
  7. annotation.zip = placemark.postalCode;
  8. annotation.coordinate = geocoder.coordinate;
  9. [mapView addAnnotation:annotation];
  10.  
  11. [annotation release];
  12. geocoder.delegate = nil;
  13. [geocoder autorelease];
  14.  
  15. [activity stopAnimating];
  16. activity.hidden = YES;
  17. }

成功编码后需要在该方法中创建标注对象(MapLocation)。MapLocation 是我们自定义的实现MKAnnotation协议标注对象。 该方法的placemark是MKPlacemark获得很多地理信息,详细见下表。

[mapView addAnnotation:annotation]; 为地图添加标注,该方法将会触发mapView:viewForAnnotation:方法回调。

MKPlacemark类属性

addressDictionary  地址信息的dictionary

thoroughfare  指定街道级别信息

subThoroughfare  指定街道级别的附加信息

locality  指定城市信息

subLocality  指定城市信息附加信息

administrativeArea  行政区域

subAdministrativeArea  行政区域附加信息

country  国家信息

countryCode  国家代号

postalCode  邮政编码

失败编码回调方法

  1. - (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error {
  2. UIAlertView *alert = [[UIAlertView alloc]
  3. initWithTitle:@"地理解码错误息"
  4. message:@"地理代码不能识别"
  5. delegate:nil
  6. cancelButtonTitle:@"Ok"
  7. otherButtonTitles:nil];
  8. [alert show];
  9. [alert release];
  10.  
  11. geocoder.delegate = nil;
  12. [geocoder autorelease];
  13.  
  14. [activity stopAnimating];
  15. }

MKMapViewDelegate

是地图视图委托对象,本例子我们使用的方法:

- mapView:viewForAnnotation:为地图设置标注时候回调方法。

-mapViewDidFailLoadingMap:withError:地图加载错误时候回调方法。

地图标注回调方法

  1. #pragma mark Map View Delegate Methods
  2. - (MKAnnotationView *) mapView:(MKMapView *)theMapView viewForAnnotation:(id <MKAnnotation>) annotation {
  3.  
  4. MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"PIN_ANNOTATION"];
  5. if(annotationView == nil) {
  6. annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation
  7. reuseIdentifier:@"PIN_ANNOTATION"] autorelease];
  8. }
  9. annotationView.canShowCallout = YES;
  10. annotationView.pinColor = MKPinAnnotationColorRed;
  11. annotationView.animatesDrop = YES;
  12. annotationView.highlighted = YES;
  13. annotationView.draggable = YES;
  14. return annotationView;
  15. }

与表格视图单元格处理类似,地图标注对象由于会很多,因此需要重复利用,通过

dequeueReusableAnnotationViewWithIdentifier方法可以查找可重复利用的标注对象,以达到节省内存的目的。

annotationView.canShowCallout = YES;指定标注上的插图,点击图钉有气泡显示。

annotationView.pinColor 设置图钉的颜色。

annotationView.animatesDrop动画效果。

地图加载失败回调方法

  1. - (void)mapViewDidFailLoadingMap:(MKMapView *)theMapView withError:(NSError *)error {
  2. UIAlertView *alert = [[UIAlertView alloc]
  3. initWithTitle:@"地图加载错误"
  4. message:[error localizedDescription]
  5. delegate:nil
  6. cancelButtonTitle:@"Ok"
  7. otherButtonTitles:nil];
  8. [alert show];
  9. [alert release];
  10. }

自定义地图标注对象 

  1. #import <Foundation/Foundation.h>
  2. #import <MapKit/MapKit.h>
  3.  
  4. @interface MapLocation : NSObject <MKAnnotation, NSCoding> {
  5. NSString *streetAddress;
  6. NSString *city;
  7. NSString *state;
  8. NSString *zip;
  9.  
  10. CLLocationCoordinate2D coordinate;
  11. }
  12. @property (nonatomic, copy) NSString *streetAddress;
  13. @property (nonatomic, copy) NSString *city;
  14. @property (nonatomic, copy) NSString *state;
  15. @property (nonatomic, copy) NSString *zip;
  16. @property (nonatomic, readwrite) CLLocationCoordinate2D coordinate;
  17. @end

作为地图标注对象实现MKAnnotation协议是必须的,只有实现该协议才能使该类成为标注类。实现NSCoding协议是可选的,实现该协议可以使标注对象能够复制。 里面的属性有哪些要看你自己的需要。

MapLocation.m

  1. - (NSString *)title {
  2. return @"您的位置!";
  3. }
  4. - (NSString *)subtitle {
  5.  
  6. NSMutableString *ret = [NSMutableString string];
  7. if (streetAddress)
  8. [ret appendString:streetAddress];
  9. if (streetAddress && (city || state || zip))
  10. [ret appendString:@" • "];
  11. if (city)
  12. [ret appendString:city];
  13. if (city && state)
  14. [ret appendString:@", "];
  15. if (state)
  16. [ret appendString:state];
  17. if (zip)
  18. [ret appendFormat:@", %@", zip];
  19.  
  20. return ret;
  21. }

title 和subtitle 是MKAnnotation协议要求实现的方法。

MapLocation.m

  1. #pragma mark -
  2. - (void)dealloc {
  3. [streetAddress release];
  4. [city release];
  5. [state release];
  6. [zip release];
  7. [super dealloc];
  8. }
  9. #pragma mark -
  10. #pragma mark NSCoding Methods
  11. - (void) encodeWithCoder: (NSCoder *)encoder {
  12. [encoder encodeObject: [self streetAddress] forKey: @"streetAddress"];
  13. [encoder encodeObject: [self city] forKey: @"city"];
  14. [encoder encodeObject: [self state] forKey: @"state"];
  15. [encoder encodeObject: [self zip] forKey: @"zip"];
  16. }
  17. - (id) initWithCoder: (NSCoder *)decoder {
  18. if (self = [super init]) {
  19. [self setStreetAddress: [decoder decodeObjectForKey: @"streetAddress"]];
  20. [self setCity: [decoder decodeObjectForKey: @"city"]];
  21. [self setState: [decoder decodeObjectForKey: @"state"]];
  22. [self setZip: [decoder decodeObjectForKey: @"zip"]];
  23. }
  24. return self;
  25. }

encodeWithCoder:和initWithCoder:是NSCoding协议要求实现方法。

3 Web地图

在iOS中我们还可以使用Web地图。

  1. - (IBAction)webMap:(id)sender {
  2. CLLocation *lastLocation = [locationManager location];
  3. if(!lastLocation)
  4. {
  5. UIAlertView *alert;
  6. alert = [[UIAlertView alloc]
  7. initWithTitle:@"系统错误"
  8. message:@"还没有接收到数据!"
  9. delegate:nil cancelButtonTitle:nil
  10. otherButtonTitles:@"OK", nil];
  11.  
  12. [alert show];
  13. [alert release];
  14. return;
  15. }
  16.  
  17. NSString *urlString = [NSString stringWithFormat:
  18. @"http://maps.google.com/maps?q=Here+I+Am!@%f,%f",
  19. lastLocation.coordinate.latitude,
  20. lastLocation.coordinate.longitude];
  21. NSURL *url = [NSURL URLWithString:urlString];
  22.  
  23. [[UIApplication sharedApplication] openURL:url];
  24. }

http://maps.google.com/maps?q=Here+I+Am!@%f,%f是请求Web地图的网站,q后面上参数。

[[UIApplication sharedApplication] openURL:url];打开iOS内置的浏览器,即在内置浏览器中打开地图。

 
 

ios开发——实用技术OC篇&地图与定位的更多相关文章

  1. iOS开发——实用技术OC篇&单例模式的实实现(ACR&MRC)

    单例模式的实实现(ACR&MRC) 在iOS开发中单例模式是一种非常常见的模式,虽然我们自己实现的比较少,但是,系统却提供了不少的到来模式给我们用,比如最常见的UIApplication,No ...

  2. iOS开发——实用技术OC篇&简单抽屉效果的实现

    简单抽屉效果的实现 就目前大部分App来说基本上都有关于抽屉效果的实现,比如QQ/微信等.所以,今天我们就来简单的实现一下.当然如果你想你的效果更好或者是封装成一个到哪里都能用的工具类,那就还需要下一 ...

  3. iOS开发——实用技术OC篇&8行代码教你搞定导航控制器全屏滑动返回效果

    8行代码教你搞定导航控制器全屏滑动返回效果 前言 如果自定了导航控制器的自控制器的leftBarButtonItem,可能会引发边缘滑动pop效果的失灵,是由于 self.interactivePop ...

  4. iOS开发——实用技术OC篇&事件处理详解

    事件处理详解 一:事件处理 事件处理常见属性: 事件类型 @property(nonatomic,readonly) UIEventType     type; @property(nonatomic ...

  5. ios开发——实用技术OC篇》倒计时实现的两种方法

    倒计时实现的两种方法 timeFireMethod函数,timeFireMethod进行倒计时的一些操作,完成时把timer给invalidate掉就ok了,代码如下: secondsCountDow ...

  6. iOS开发——实战OC篇&环境搭建之Xib(玩转UINavigationController与UITabBarController)

    iOS开发——实战OC篇&环境搭建之Xib(玩转UINavigationController与UITabBarController)   前面我们介绍了StoryBoard这个新技术,和纯技术 ...

  7. iOS开发——实战OC篇&环境搭建之纯代码(玩转UINavigationController与UITabBarController)

    iOS开发——实战OC篇&环境搭建之纯代码(玩转UINavigationController与UITabBarController)   这里我们就直接上实例: 一:新建一个项目singleV ...

  8. ios开发——实用技术OC-Swift篇&触摸与手势识别

    iOS开发学习之触摸事件和手势识别   iOS的输入事件 触摸事件 手势识别 手机摇晃 一.iOS的输入事件   触摸事件(滑动.点击) 运动事件(摇一摇.手机倾斜.行走),不需要人为参与的 远程控制 ...

  9. iOS开发——实战OC篇&环境搭建之StoryBoard(玩转UINavigationController与UITabBarController)

      环境搭建之StoryBoard(玩转UINavigationController与UITabBarController)   研究了这么就IOS开发,都没有所处一个像样或者自己忙一点的项目.最近自 ...

随机推荐

  1. mysql 触发器学习(可以将mysql数据同步到redis)

    1. 一个简单的例子 1.1. 创建表: create table t(s1 integer); 1.2. 触发器: delimiter | create trigger t_trigger befo ...

  2. 多线程程序设计学习(9)worker pattern模式

    Worker pattern[工作模式]一:Worker pattern的参与者--->Client(委托人线程)--->Channel(通道,里边有,存放请求的队列)--->Req ...

  3. C++学习笔记:List容器

    http://www.cplusplus.com/reference/list/list/ #include <list> list l:初始化一个0大小的表 list l(10):初始化 ...

  4. 我的WCF之旅(1):创建一个简单的WCF程序

    为了使读者对基于WCF的编程模型有一个直观的映像,我将带领读者一步一步地创建一个完整的WCF应用.本应用功能虽然简单,但它涵盖了一个完整WCF应用的基本结构.对那些对WCF不是很了解的读者来说,这个例 ...

  5. Ildasm.exe(MSIL 反汇编程序)

    MSIL 反汇编程序是 MSIL 汇编程序 (Ilasm.exe) 的伙伴工具. Ildasm.exe 采用包含 Microsoft 中间语言 (MSIL) 代码的可迁移可执行 (PE) 文件,并创建 ...

  6. [Tommas] 测试用例覆盖率(一)

    一.测试用例的切面设计 所谓测试切面设计,其实就是测试用例大项的划分.测试用例划分的经典方法是瀑布模型,也就是从上到下,逐渐细分,大模块包括小模块,小模块包括更小的模块.但仅仅如此是不够的,我们还要从 ...

  7. 获取EntityFrameWork返回的错误和ModelState中的错误

    都是通过循环才能找到具体的错误信息 具体方法参见这两篇文章: EntityFrameWork: http://www.cnblogs.com/shouzheng/archive/2012/04/19/ ...

  8. SMG12232ZK标准字符点阵型液晶显示模块的演示程序[C51编程语言][MCS51并行接口方式]

    //SMG12232ZK标准字符点阵型液晶显示模块的演示程序[C51编程语言][MCS51并行接口方式] //应用产品: SMG12232ZK标准中文字符点阵型液晶显示模块 // 本演示程序适用于SM ...

  9. Mongodb操作总结

    1.Mongovue里面可以直接group by ,这个时候一定要注意,group by的任何条件的是 json, 注意当值是Int,非string型的时候,值不要加上双引号 2.注意group by ...

  10. python学习之copy模块

    Python中的对象之间赋值时是按引用传递的,如果需要拷贝对象,需要使用标准库中的copy模块. 1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象.2. copy.deepc ...