首页 > 代码库 > 简易地图(MKMapView,CLLocationManagerDelegate,CLGeocoder)

简易地图(MKMapView,CLLocationManagerDelegate,CLGeocoder)

概要

       本章主要简示了IOS里面位置服务的使用,包括定位,地图,地图标记以及地图定位。由于现在的地图开发和以前的差别比较大,而且地图涉及的东西相对而言复杂点,所以本实验耗时比较多,有的地方还存在一些问题。


结果展示


       注意文本框的两个数字是当前的经纬度,地图视图切换是切换到该经纬度的位置,最后红色的那个标注即为地图中的经纬度,不过由于经纬度解析部分有问题,所以未能显示经纬度的对应地址是什么。(示例里面不是使用代理来解析经纬度的,使用的是CLGeocoder,因为以前使用的代理官方建议不再使用了。


流程概要

1.在开始工程之前需要知道主要步骤:a.定位当前的地址 b.解析经纬度获取对应的地址,然后地图视图切换到该位置 c.在地图上标注该位置

2.定位部分因为看到的教程较老,所以实际操作有差别,最新的定位需要增加授权。其主要方法是在修改info.list文件,然后再代码里面添加授权代码。如下所示:

/*
1.Info.plist中加入两个缺省没有的字段
  NSLocationAlwaysUsageDescription
  NSLocationWhenInUseUsageDescription
  并设置值为YES
*/
  
//2.在启动定位前设置授权
// 开始定位
-(void)onLocate
{
    self._textLocationInfo.text = @"";
    self._locateManage = [[CLLocationManager alloc] init];
    self._locateManage.delegate = self;
    self._locateManage.desiredAccuracy = kCLLocationAccuracyBest;
    self._locateManage.distanceFilter = 1000;
   
    // 新版本需要授权
    if ([[[UIDevice currentDevice] systemVersion] doubleValue] > 8.0)
    {
        [self._locateManage requestWhenInUseAuthorization];
    }
    
    [self._locateManage startUpdatingLocation];
    [self._locateActivityIndicator startAnimating];
}

3.实现定位代理的协议和地图代理协议,主要是完成以下方法:

#pragma 实现协议CLLocationManagerDelegate
// 定位成功调用该方法,数组里面最后的成员为最新的地址
- (void)locationManager:(CLLocationManager *)manager
     didUpdateLocations:(NSArray *)locations

// 授权完成调用该方法,可查看授权状态
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status;
// 定位失败调用该方法
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error;


#pragma 实现协议MKMapViewDelegate
// 画标注
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;

4.在获取地址成功后,根据地址中的经纬度设置地图视图,然后使用CLGeocoder解析经纬度地址。

5.解析出地址后需要在地图上标注出当前位置,此时需要新建一个类,实现标注的协议,指定标注的经纬度、标题以及子标题

6.完成后,停止定位


主要代码

h文件

//
//  ViewController.h
//  FindMe
//
//  Created by God Lin on 14/12/13.
//  Copyright (c) 2014年 arbboter. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>

@interface ViewController : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate>
{
    MKMapView* _mapView;
    UIButton* _buttonLocate;
    UITextView* _textLocationInfo;
    UIActivityIndicatorView* _locateActivityIndicator;
    
    CLLocationManager* _locateManage;
}

@property (nonatomic, retain) MKMapView* _mapView;
@property (nonatomic, retain) UIButton* _buttonLocate;
@property (nonatomic, retain) UITextView* _textLocationInfo;
@property (nonatomic, retain) UIActivityIndicatorView* _locateActivityIndicator;
@property (nonatomic, retain) CLLocationManager* _locateManage;
@end

m文件

//
//  ViewController.m
//  FindMe
//
//  Created by God Lin on 14/12/13.
//  Copyright (c) 2014年 arbboter. All rights reserved.
//

#import "ViewController.h"
#import "MapLocation.h"

@interface ViewController ()

@end

@implementation ViewController

@synthesize _buttonLocate, _locateActivityIndicator, _mapView, _textLocationInfo;
@synthesize _locateManage;

// 界面控件布局
-(void)autoLayout
{
    CGFloat _x = self.view.frame.origin.x;
    CGFloat _y = self.view.frame.origin.y;
    CGFloat _w = self.view.frame.size.width;
    CGFloat _h = self.view.frame.size.height;
    
    CGFloat xEdge = 10;
    CGFloat yEdge = 10;
    CGFloat x = _x + xEdge;
    CGFloat y = _y + 2*yEdge;
    CGFloat w = _w - 2*xEdge;
    CGFloat h = 50;
    
    self._mapView.frame = CGRectMake(x, y, w, _h - y - yEdge - h);
    
    y = self._mapView.frame.origin.y + self._mapView.frame.size.height + yEdge;
    h -= 5;
    self._buttonLocate.frame = CGRectMake(x, y, w/5, h);
    self._buttonLocate.layer.cornerRadius = 10;
    self._buttonLocate.layer.borderWidth = 1;
    [self._buttonLocate setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [self._buttonLocate setTitle:@"Locate" forState:UIControlStateNormal];
    
    CGFloat xSameLevelEdge = 2;
    x = x + self._buttonLocate.frame.size.width;
    self._textLocationInfo.frame = CGRectMake(x+xSameLevelEdge, y, 4*w/5-xSameLevelEdge, h);
    self._textLocationInfo.layer.borderWidth = 1;
    self._textLocationInfo.layer.cornerRadius = 10;
    self._textLocationInfo.editable = NO;
    
    self._locateActivityIndicator.frame = CGRectMake(0,0, h*2, h*2);
    [self._locateActivityIndicator setCenter:CGPointMake(_w/2, _h/2)];
    [self._locateActivityIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge];
    self._locateActivityIndicator.color = [UIColor blackColor];
}

// 开始定位
-(void)onLocate
{
    self._textLocationInfo.text = @"";
    self._locateManage = [[CLLocationManager alloc] init];
    self._locateManage.delegate = self;
    self._locateManage.desiredAccuracy = kCLLocationAccuracyBest;
    self._locateManage.distanceFilter = 1000;
   
    // 新版本需要授权
    if ([[[UIDevice currentDevice] systemVersion] doubleValue] > 8.0)
    {
        [self._locateManage requestWhenInUseAuthorization];
    }
    
    [self._locateManage startUpdatingLocation];
    [self._locateActivityIndicator startAnimating];
}

-(void)stopLocate
{
    if(self._locateManage)
    {
        [self._locateManage stopUpdatingLocation];
        self._locateManage.delegate = nil;
        [self._locateManage release];
        self._locateManage = nil;
        [self._locateActivityIndicator stopAnimating];
    }
}
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self._mapView = [[MKMapView alloc] init];
    [self.view addSubview:self._mapView];
    
    self._buttonLocate = [[UIButton alloc] init];
    [self._buttonLocate addTarget:self action:@selector(onLocate) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self._buttonLocate];
    
    self._textLocationInfo = [[UITextView alloc] init];
    [self.view addSubview:self._textLocationInfo];
    
    self._locateActivityIndicator = [[UIActivityIndicatorView alloc] init];
    [self.view addSubview:self._locateActivityIndicator];
    
    [self autoLayout];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)dealloc
{
    [_locateActivityIndicator release];
    [_mapView release];
    [_textLocationInfo release];
    [_buttonLocate release];
    [super dealloc];
}

#pragma 实现协议CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager
     didUpdateLocations:(NSArray *)locations
{
    NSLog(@"%@", locations);
    CLLocation* curLocation = [locations lastObject];
    
    // 地图定位到当前位置
    MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(curLocation.coordinate, 1000, 1000);
    viewRegion = [self._mapView regionThatFits:viewRegion];
    [self._mapView setRegion:viewRegion animated:YES];
    
    // 解析经纬度为地址,在地图上添加标注
    MapLocation* annotation = [[MapLocation alloc] init];
    annotation.coordinate = curLocation.coordinate;
    CLGeocoder* geoCoder = [[CLGeocoder alloc] init];
    [geoCoder reverseGeocodeLocation:curLocation completionHandler:^(NSArray *placemarks, NSError *error)
    {
        if(error)
        {
            NSLog(@"CLGeocoder error -> %@", [error localizedDescription]);
        }
        else
        {
            CLPlacemark *placemark = [placemarks lastObject];
            NSString* startAddressString = [NSString stringWithFormat:@"%@ %@ %@ %@ %@ %@",
                                            placemark.subThoroughfare, placemark.thoroughfare,
                                            placemark.postalCode, placemark.locality,
                                            placemark.administrativeArea,
                                            placemark.country];
            NSLog(@"地址为:%@", startAddressString);
            
            
            annotation._city = placemark.locality;
            annotation._country = placemark.country;
            annotation._streetAddrerss = placemark.thoroughfare;
            annotation._zip = placemark.postalCode;
            annotation._state = placemark.name;
        }
    }];
    [self._mapView addAnnotation:annotation];
    [geoCoder release];
    
    // 设置文本信息
    NSString* stringLocation = [[NSString alloc] initWithFormat:@"%@\n%@", annotation.subtitle, annotation.title];
    self._textLocationInfo.text = stringLocation;
    [stringLocation release];
    
    [annotation release];
    [self stopLocate];
}

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    NSLog(@"Authorization finished. status = %d", status);
}

- (void)locationManager:(CLLocationManager *)manager
       didFailWithError:(NSError *)error
{
    UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Locate Failed" message:[error description] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    NSLog(@"%@", [error description]);
    [alert show];
    [alert release];
    [self._locateActivityIndicator stopAnimating];
    
    [self stopLocate];
}

#pragma 实现协议MKMapViewDelegate
// 画标注
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;
{
    MKPinAnnotationView* annotationView = (MKPinAnnotationView*)[self._mapView dequeueReusableAnnotationViewWithIdentifier:@"annotationView"];
    if(annotationView == nil)
    {
        annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"annotationView"] autorelease];
    }
    annotationView.canShowCallout = YES;
    annotationView.pinColor = MKPinAnnotationColorRed;
    annotationView.animatesDrop = YES;
    return annotationView;
}

@end

(实现标注协议的类见工程代码)


项目工程

简易地图(MKMapView,CLLocationManagerDelegate,CLGeocoder)