IOS之地图和定位应用开发

11.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

定位服务实例

wps_clip_image-13869

项目WhereAmI:

WhereAmIViewController.h

复制代码

1#import <UIKit/UIKit.h>#import <CoreLocation/CoreLocation.h>@interface ViewController : UIViewController<CLLocationManagerDelegate> { 2    CLLocationManager* locationManager; 3} 4 5@property (strong, nonatomic)    CLLocationManager* locationManager; 6@property (retain, nonatomic) IBOutlet UILabel *longitudeText; 7@property (retain, nonatomic) IBOutlet UILabel *latituduText; 8@property (retain, nonatomic) IBOutlet UIActivityIndicatorView *activity;- (IBAction)findMe:(id)sender;- (IBAction)webMap:(id)sender;@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位的浮点数。

11.2 iOS地图

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

其核心是MKMapView类使用。

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

wps_clip_image-5334

地图开发一般过程

wps_clip_image-6593

wps_clip_image-616

添加MapKit类库

MapKit.framework

MapMeViewController.h

复制代码

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

复制代码

CLLocationManagerDelegate是定位服务委托。

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

   -mapView:viewForAnnotation:

   -mapViewDidFailLoadingMap:withError:

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

   – reverseGeocoder:didFindPlacemark:

   – reverseGeocoder:didFailWithError:

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

复制代码

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

复制代码

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"];    if(annotationView == nil) { 5        annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation 6                                                          reuseIdentifier:@"PIN_ANNOTATION"] autorelease]; 7    } 8    annotationView.canShowCallout = YES; 9    annotationView.pinColor = MKPinAnnotationColorRed; 10    annotationView.animatesDrop = YES; 11    annotationView.highlighted = YES; 12    annotationView.draggable = YES;    return annotationView; 13}

复制代码

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

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

复制代码

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

MapLocation.m

复制代码

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

复制代码

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}#pragma mark -#pragma mark NSCoding Methods 9- (void) encodeWithCoder: (NSCoder *)encoder { 10    [encoder encodeObject: [self streetAddress] forKey: @"streetAddress"]; 11    [encoder encodeObject: [self city] forKey: @"city"]; 12    [encoder encodeObject: [self state] forKey: @"state"]; 13    [encoder encodeObject: [self zip] forKey: @"zip"]; 14}- (id) initWithCoder: (NSCoder *)decoder  {    if (self = [super init]) { 15        [self setStreetAddress: [decoder decodeObjectForKey: @"streetAddress"]]; 16        [self setCity: [decoder decodeObjectForKey: @"city"]]; 17        [self setState: [decoder decodeObjectForKey: @"state"]]; 18        [self setZip: [decoder decodeObjectForKey: @"zip"]]; 19    }    return self; 20}

复制代码

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

11.3 Web地图

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

wps_clip_image-3276

复制代码

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

复制代码

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

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

点赞
收藏

评论区

加载中...

相关推荐

Selenium 详解CSS定位

xpath定位是“屠龙刀”,那CSS定位就是"倚天剑了",相对xpath来说,具有语法简单,定位速度快等优点一、属性定位1、可以通过元素的id,class,tag标签这三个属性直接定位  表示id属性,如:kw.  表示class属性,如:.s\_ipt直接用标签名称,如:inpu

IOS定位服务的应用

IOS定位服务的应用一、授权的申请与设置在IOS8之后,IOS的定位服务做了优化,若要使用定位服务,必须先获取用户的授权。首先需要在info.plist文件中添加一个键:NSLocationAlwaysUsageDescription或者NSLocationWhenInUseUsageDescription。其中NS

Python+Selenium自动化篇

本篇文字主要学习selenium定位页面元素的集中方法,以百度首页为例子。0.元素定位方法主要有:id定位:find\_element\_by\_id('')name定位:find\_element\_by\_name('')class定位:find\_element\_by\_class\_name(''

IP地理位置定位系统之定位系统研发

IP地理位置定位系统是一个街道级别的、实时的IP地理位置查询系统。该系统采用超高精度IP实时定位技术,通过网络测量和大数据挖掘,对IP的地理位置和相关属性进行测量,在无需硬件支持的条件下,即可对被探测目标终端IP完成定位。定位系统的研发核心是IP地理位置定位算法,包含如何划分IP所属功能块和地域块、设计IP定位算法、采用什么样的相似度比较策略、IP地理位

Android笔记

  首先是权限,因为WIFI也是可以用于定位的,只是精度没那么高而已,所以6.0之后的权限系统对WIFI的权限进行了限制,除了需要日常的WIFI操作权限之外,还需要定位权限,否则会获取不到WIFI的信息。<!完全的网络访问权限<usespermissionandroid:name"android.pe

RobotFramework自动化测试之元素定位

前言:最近在做基于RF框架的Web自动化测试,其中涉及到元素的定位,主要用到id、name、xpath、css四中定位方法,尤其后面的两种方法特别有效,可以解决大部分的定位问题。