2014-11-03 19:20:34 Lazar_lvq 阅读数 415
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3672 人正在学习 去看看 许英俊

11.1 iOS定位服务

11.2 iOS地图

11.3 Web地图

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

复制代码
#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类使用。

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

wps_clip_image-5334

地图开发一般过程

wps_clip_image-6593

wps_clip_image-616

添加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地图。

wps_clip_image-3276

 

 

复制代码
- (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];
}
复制代码

 

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

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


2016-01-20 21:46:17 jinganglong123 阅读数 2333
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3672 人正在学习 去看看 许英俊

ios1.0:

iOS系统诞生于200711的Macworld上,当天公布了iOS的初代系统,当时它的名字是iPhone OS X。

ios2.0:

紧接着2008711,在新一代iPhone3G正式发售当天,iPhone OS 2.0(iOS 2.0)也随之正式推出,iPhone3G采用了全新的外形设计,并且在原来的基础上增加了对3G网络的支持,同时也增加了对A-GPS的支持,内置中文包,可以键盘手写双输入等

ios 3.0:

200969出现更接近现在用户的iPhone 3GS,该机发布的同时也一通为我们带来了iPhone OS 3.0(iOS 3.0)系统。iPhone3GS型号中的S也代表了Speed速度的意思,由于硬件上的提升所以3GS在速度上有了不小的升级,同时也增加了对复制粘贴等文本操作的支持。

ios 4.0、ios 5.0 、ios 6.0:

接着的iPhone 4的iOS 4.0(此时正式改名为iOS)以及iPhone 4S的iOS 5.0和最新的iPhone 5以及iOS 6.0,分别于20106212011105以及2012919与广大消费者正式见面,其中系统方面最大的提升是iOS 4以后增加了对Retina屏幕以及对多任务管理的支持,iOS 5所带来的iCloud和Siri语音助手,这几项改进再次让iPhone成为了全球的焦点,同时苹果公司也顺利成长的成为了全球市值最高的公司。

ios 7.0:

北京时间2013911日凌晨苹果在秋季发布会上宣布iOS7于9月18日正式推出,2013年9月19日凌晨1点开放免费下载更新。

iOS 7iOS系统是继iOS3iOS 6以来最大一次升级它采用全新的图标界面设计总计有上百项改动其中包括控制中心通知中心新的多任务处理等等

iOS 7iOS面世以来在用户界面上做出改变最大的一个操作系统iOS 7抛弃了以往的拟物化设计而采用了扁平化设计

ios 8.0:

2014-09-18凌晨1点,苹果向中国用户推送了iOS8正式版的更新。

ios 9.0:

2015年9月24日凌晨,苹果公司为iOS9正式版推送了iOS9.0.1进行了第一次更新。除了对bug 内容的修复外,这次更新还为用户们带来更为先进的 iPad 多任务处理功能,Newsapp 应用的改善,搜索和 Siri 性能的增强,同时还对电池管理的效率进行了提升,并且升级包的大小也才35.4 M 而已。本次更新的版本可以与 iPhone 4s,iPad2,第五代iPod touch 以及更高版本设备相兼容。

大家有没有发现一个特点:ios的大版本号+6=该ios版本推出的年代末两位

2012-10-14 23:01:00 weixin_30646505 阅读数 3
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3672 人正在学习 去看看 许英俊

11.1 iOS定位服务

11.2 iOS地图

11.3 Web地图

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

#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类使用。

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

wps_clip_image-5334

地图开发一般过程

wps_clip_image-6593

wps_clip_image-616

添加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地图。

wps_clip_image-3276

 

 

- (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];
}

 

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

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

 

注:
1 本教程是基于关东升老师的教程
2 基于黑苹果10.6.8和xcode4.2
3 本人初学,有什么不对的望指教
4 教程会随着本人学习,持续更新
5 教程是本人从word笔记中拷贝出来了,所以格式请见谅

转载于:https://www.cnblogs.com/syxchina/archive/2012/10/14/2723522.html

2014-12-05 16:36:31 yu_and_xiami 阅读数 198
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3672 人正在学习 去看看 许英俊

11.1 iOS定位服务

11.2 iOS地图

11.3 Web地图

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

复制代码
#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类使用。

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

wps_clip_image-5334

地图开发一般过程

wps_clip_image-6593

wps_clip_image-616

添加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地图。

wps_clip_image-3276

 

 

复制代码
- (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];
}
复制代码

 

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

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

 

2014-01-08 10:47:05 hmxiao_1983 阅读数 447
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3672 人正在学习 去看看 许英俊

11.1 iOS定位服务

11.2 iOS地图

11.3 Web地图

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

复制代码
#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类使用。

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

wps_clip_image-5334

地图开发一般过程

wps_clip_image-6593

wps_clip_image-616

添加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地图。

wps_clip_image-3276

 

 

复制代码
- (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];
}
复制代码

 

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

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

 

注: 
1 本教程是基于关东升老师的教程 
2 基于黑苹果10.6.8和xcode4.2 
3 本人初学,有什么不对的望指教 
4 教程会随着本人学习,持续更新 
5 教程是本人从word笔记中拷贝出来了,所以格式请见谅

没有更多推荐了,返回首页