ios 支持三种检测当前位置的方式:手机基站、WiFi 、和 GPS,其中GPS是经度最高的,同时也是最耗费手机电量的。一般情况下在室内是无法通过GPS获取位置信息的,通过WiFi获取位置的原理是通过网络提供商的IP地址信息来获取位置,经度不是很高,最好是通过手机基站获取位置,手机开机后连接附近的基站塔获取信号,通过基站可以得到手机所在的位置信息,基站越密集,所获取的位置信息经度就越高。
IOS SDK 提供的Core Location能比较好的提供获取位置信息的功能,获取位置信息涉及如下几个类,CLLocationManager(位置管理器),CLLocation, CLLocationManagerDelegate(协议、提供委托方法),CLLocationCoodinate2D(存储坐标位置)另外CLLocationManager还有几个属性;
desiredAccuracy:位置的精度属性取值有如下几种:
kCLLocationAccuracyBest 精确度最佳
kCLLocationAccuracynearestTenMeter 精确度10m以内
kCLLocationAccuracyHundredMeters 精确度100m以内
kCLLocationAccuracyKilometer 精确度1000m以内
kCLLocationAccuracyThreeKilometers 精确度3000m以内
distanceFilter:是距离过滤器,为了减少对定位装置的轮询次数,位置的改变不会每次都去通知委托,而是在移动了足够的距离时才通知委托程序,它的单位是米
delegate:响应CLLocationManagerdelegate的对象
下面来构建一个获取位置的例子:
首先建立一个Single View Application工程,然后引入coreLocation.framework, 并在ViewController.h中修改如下:
#import <UIKit/UIKit.h>
#import <CoreLocation/CLLocationManager.h>
#import <CoreLocation/CoreLocation.h>
@interface ViewController : UIViewController<CLLocationManagerDelegate>
{
}
@property (nonatomic,retain) CLLocationManager *locManager;
@property (retain, nonatomic) IBOutlet UILabel *lonLabel;
@property (retain, nonatomic) IBOutlet UILabel *latLabel;
@end
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_locManager = [[CLLocationManager alloc] init];////初始化位置管理器
_locManager.delegate = self;//设置代理
_locManager.desiredAccuracy = kCLLocationAccuracyBest;//设置位置经度,可以设为最优,装置会自动用最精确的方式去定位
_locManager.distanceFilter = 100;//设置每隔100米更新位置
[_locManager startUpdatingLocation];//开始定位服务
}
//协议中的方法,作用是每当位置发生更新时会调用的委托方法. 可以得到新位置,旧位置,CLLocation里面有经度纬度的坐标值,同时CLLocation还有个属性horizontalAccuracy,用来得到水平上的精确度,单位为米
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
//结构体,存储位置坐标
CLLocationCoordinate2D loc = [newLocation coordinate];
float longitude = loc.longitude;
float latitude = loc.latitude;
self.lonLabel.text = [NSString stringWithFormat:@"%f",longitude];
self.latLabel.text = [NSString stringWithFormat:@"%f",latitude];
}
//当位置获取或更新失败会调用的方法
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSString *errorMsg = nil;
if ([error code] == kCLErrorDenied)
{
errorMsg = @"访问被拒绝";
}
if ([error code] == kCLErrorLocationUnknown)
{
errorMsg = @"获取位置信息失败";
}
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Location"
message:errorMsg
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil, nil];
[alertView show];
[alertView release];
}
- (void)viewDidUnload
{
self.lonLabel = nil;
self.latLabel = nil;
[super viewDidUnload];
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc
{
[_locManager stopUpdatingLocation];
[_lonLabel release];
[_latLabel release];
[super dealloc];
}
@end
coreLocation 中得到的定位信息都是以经度和纬度等表示的地理信息,很多时候我们需要把它反向编码成普通人能读懂的地理位置描述如:X国XX市XX区XX街道XX号,这就需要用到MapKit中的一个地理位置反向编码工具:MKReverseGeocoder
用法:
1、首先要实现协议MKReverseGeocoderDelegate,因为将坐标信息发到服务器再反回来需要一定的时间,所以为了防止阻塞,发出信息后并不知道什么时候会返回信息,信息返回时会通知委托方法。这里实现这个类主要是为了实现2个方法如下:
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error
{
NSLog(@"MKReverseGeocoder has failed.");
}
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark
{
NSLog(@"当前地理信息为:%@",placemark);
}
didFailWithError:这个方法是来处理返回错误信息的,didFindPlacemark则是地理信息返回了,地理信息包含在placemark里面,此对象中包含国家,城市,区块,街道等成员变量。
然后可以init一个反向编码器,然后发出请求了:
MKReverseGeocoder *reverseGeocoder = [[MKReverseGeocoder alloc] initWithCoordinate:coordinate];
reverseGeocoder.delegate = self;
[reverseGeocoder start];
MKReverseGeocoder 除了start方法,还有cancel方法来取消方法。