关闭

IOS地图开发与定位

标签: IOS地图开发与定位移动开发
737人阅读 评论(0) 收藏 举报
分类:

分类: 移动开发/ IOS/ 文章

来源:http://blog.csdn.net/zhuiyi316/article/details/8306615

首先我们需要一个视图去呈现地图,苹果自带一个关于地图视图的类,名字叫MKMapView,可以在MapKit这个框架找到,所以用到地图需要在头文件中#import ,这样大家已经可以看到一个地图了,可以拖拽以及缩放。

下面是重点介绍如何去操作地图

在这里我想介绍关于地图几个重要的属性和方法。

第一个属性:@property (nonatomic) MKMapType mapType;

这是一个结构体,有三个属性,决定地图的呈现风格。(在全房应用中没有用到,但我还是在这里提及一下)下面是关于这三个属性的介绍:

standard:标注地图,显示街道和街道名

Satellite:卫星图片区

Hybrid:卫星图,同时在相应区域有标注了街道和街道名

第二个属性:@property (nonatomic) MKCoordinateRegion region;

同样这也是一个结构体,看到名字应该想到这是一个标注视图上显示的地图区域。基本上一个区域是由中心点,和经度、纬度的跨越度决定的,这个跨越度也就是视图上的最大纬度或经度和最小纬度或经度之差。

typedef struct {

    CLLocationCoordinate2D center;

    MKCoordinateSpan span;

} MKCoordinateRegion;

给出这个结构体的定义应该会让大家明白很多。

这里大家可以直接去修改这个属性来改变地图在视图上的呈现区域,这样是不会产生动画效果的。如果要产生动画效果,大家可以用这个方法:

       (void)setRegion:(MKCoordinateRegion)region animated:(BOOL)animated;

       大家理解区域还有相关的只改变区域中心的方法可以自己看一下,在MKMapView.h的头文件中。

第三个属性:@property (nonatomic) BOOL showsUserLocation;


这个是用来决定是否显示用户位置,图中的蓝点是系统自带的用来显示用户位置。

这是几个常用的属性,下面介绍一下常用的一些方法:

- (CGPoint)convertCoordinate:(CLLocationCoordinate2D)coordinate toPointToView:(UIView *)view;

- (CLLocationCoordinate2D)convertPoint:(CGPoint)point toCoordinateFromView:(UIView *)view;

- (CGRect)convertRegion:(MKCoordinateRegion)region toRectToView:(UIView *)view;

- (MKCoordinateRegion)convertRect:(CGRect)rect toRegionFromView:(UIView *)view;

这几个方法是进行视图区域和真实世界中的实际位置的转换,这个会经常用到。

介绍下面的方法前我想先解释一下“大头针”,以及它的用法


在用到地图的时候我们经常会向地图上加一些向上图那样的小视图,这些小视图都是MKAnnotationView的对象,我们称之为大头针吧。

还会有如上图的需求,也就是点击大头针会弹出一个视图,实际上它并不是视图,这个视图基本上是画上去的,会随着大头针的位置的改变而改变,也会随着信息的长度而自动伸缩,它的长度等是不能改变的,系统会很合适的改变它。

这些信息怎么放呢?我们需要自定义一个类,起名叫PinView吧。需要实现一个协议MKAnnotation;我简单的给一下头文件吧

@interface PinView : NSObject{

    CLLocationCoordinate2D coordinate;

    NSString *title;

    NSString *subtitle;

}

它简单的包含了坐标,标题,以及副标题。标题也就是上图的:金狮温泉花园,副标题也就是上图的:在售:112套。

现在我们知道了如何去制定这些信息,可是却不知道怎么把大头针放上去,下面就要用到MKMapView的几个方法了:

- (void)addAnnotation:(id )annotation;

- (void)addAnnotations:(NSArray *)annotations;


- (void)removeAnnotation:(id )annotation;

- (void)removeAnnotations:(NSArray *)annotations;

第一个方法便是添加,可是这样还不够,大头针视图的呈现方式和风格是由我们来自己来决定的,这就用到了MKMapView的委托方法(既然是委托那么我们需要设置它的代理给合适的控制器):

       (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation;

这个委托方法有两个参数,第一个是地图本身,第二个就是我们自定义的PinView对象。

还有一个返回值,就像是我们在用tableview的时候返回的cell是一样的,我们需要制订一个大头针返回,大家看一下下面的代码相信会很明白。

- (MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id )annotation

{

    static NSString *indentifer = @”QuanFangPinID”;//一个重用的标识往下看会明白的

    MKPinAnnotationView *pinView = nil;

    NSDictionary *tempDic;

    if(annotation != mV.userLocation)//显示用户位置的那个蓝点也是大头针,我不希望改变它,所以在这里要判断一下

    {

      PinView *pin = (PinView *)annotation; //强制转换一下id类型的变量

      pinView = (MKPinAnnotationView *)[mV dequeueReusableAnnotationViewWithIdentifier: indentifer];//熟悉吧,像不想tableview的重用机制,没错,地图也会重用大头针的


      if ( pinView == nil ) pinView = [[[MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier: indentifer] autorelease];//到这里一个空的MKPinAnnotationView对象基本初始化好了,可是如果仅是这样没有意义,我们要把它变成我们想的样子

      for (UIView * view in [pinView subviews])

      {

         [view removeFromSuperview];

      }

        pinView.image = nil;//这是大头阵的样子,我们设为空,在后面会在大头针上添加自己定义的视图,当然你可以在这里定义自己的样子

      pinView.canShowCallout = YES;//在点击大头针的时候会弹出那个黑框框,看看我上面发的图就知道了,这个就是决定能不能弹出的。

      pinView.animatesDrop = NO;//地图在添加大头针时的会自带下落动画,这里可以决定用不用,如果不用,你可以自己定义其它的动画,下面我会介绍

      pinView.draggable = NO;//这里决定pinView能不能拖动,应该经常会把它设为NO

   

        UIImage *image = [UIImage imageNamed:@"45.png"];

        UIImageView *imageView = [[UIImageView alloc] initWithImage:image];

      imageView.frame = CGRectMake(-13, -1, 40.5, 48);

      [pinView addSubview: imageView];

        UILabel *labelTitle = [[UILabel alloc] initWithFrame:CGRectMake(-9, 0, 35, 30)];

        labelTitle.backgroundColor = [UIColor clearColor];

        labelTitle.font = [UIFont boldSystemFontOfSize:11];

        labelTitle.textColor = [UIColor colorWithRed:62.0/255.0 green:26.0/255.0 blue:2.0/255.0 alpha:1.0];

        labelTitle.textAlignment = UITextAlignmentCenter;

        labelTitle.numberOfLines = 2;

        if(![pin.title hasSuffix:@")"])

        {

            if(currentViewState == SecondHouseingDidAppear)

            {

                tempDic = [[secondHouseArr objectForKey:@"content"] objectAtIndex:pin.tag];//[self searchPinFromDic:secondHouseArr ForTitle:pin.title];

                labelTitle.text = [NSString stringWithFormat:@"%.1fw",([[tempDic objectForKey:@"DIS_SALEPRICE"] floatValue]/10000)];

            }

            else if(currentViewState == SendHouseDidAppear)

            {

                tempDic = [[rentHouseArr objectForKey:@"content"] objectAtIndex:pin.tag];

                labelTitle.text = [NSString stringWithFormat:@"%@",[tempDic objectForKey:@"DIS_RENTPRICE"]];

            }

            [pinView addSubview:labelTitle];

        }

        else {

            tempDic = [mapShopArr objectAtIndex:pin.tag];

        }

        [labelTitle release];

      [imageView release];

   

        UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];;

    rightButton.frame = CGRectMake(0, 0, 26, 26);        rightButton.tag = pin.tag;

      pinView.rightCalloutAccessoryView = rightButton;

   }

   return pinView;

}

下面还是一个委托方法,是在你的大头针都制定好了之后调到的,相应的,基本上是在上面这个委托方法执行成功后调用。

       (void)mapView:(MKMapView *)mv didAddAnnotationViews:(NSArray *)views;

那么在这里你可以获取到所有你制定的大头针,这里你可以制订它们出现的动画,也就是上面我说的自定义动画。

其实它的委托与tableview的很相似,会在选择,取消选择的时候调用相应的委托,大家可以自己看一下MKMapView的头文件。其它的不太常用,我也没用到,敬请大家补充。

下面还是MKMapView的方法

- (void)selectAnnotation:(id )annotation animated:(BOOL)animated;

- (void)deselectAnnotation:(id )annotation animated:(BOOL)animated;

它的基本作用就是是否以动画的方式来自动选择大头针,效果就相当于我们点击或者取消点击一个大头针。


以上就是关于地图的一些基本操作,如果错误请指正,欢迎拍砖并且补充。

这里我还想介绍两样东西,与地图其实关系密切,

一个是谷歌的SVGeocoder

还一个是系统的定位管理

先说一下SVGeocoder,有这么几个方法

+ (SVGeocoder*)geocode:(NSString *)address completion:(void (^)(NSArray *placemarks, NSError *error))block;

+ (SVGeocoder*)geocode:(NSString *)address bounds:(MKCoordinateRegion)bounds completion:(void (^)(NSArray *placemarks, NSError *error))block;

+ (SVGeocoder*)geocode:(NSString *)address region:(NSString *)region completion:(void (^)(NSArray *placemarks, NSError *error))block;


+ (SVGeocoder*)reverseGeocode:(CLLocationCoordinate2D)coordinate completion:(void (^)(NSArray *placemarks, NSError *error))block;

基本上就是把经纬度和具体的地址信息互相转换。

下面介绍定位管理

需要导入#import

下面给一段创建定位管理的代码

CLLocationManager* locationManager_ = [[CLLocationManager alloc] init];//创建位置管理器

    locationManager_.delegate=self;//设置代理

    locationManager_.desiredAccuracy=kCLLocationAccuracyBest;//指定需要的精度级别

locationManager_.distanceFilter = 1000.0f;//设置距离筛选器

[locationManager_ startUpdatingLocation];//启动位置管理器

下面是两个委托方法,一个是在定位成功后的回调,一个是在失败后的回调,这是常用的。

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error

{

    [manager stopUpdatingLocation];

    [CostomUIKit mbpSuccess:@"定位失败"];

}

===========================下面方法在iOS6中已弃用=======

- (void)locationManager:(CLLocationManager *)manager

    didUpdateToLocation:(CLLocation *)newLocation

           fromLocation:(CLLocation *)oldLocation;

=============================================

上面方法在iOS6中的替代方法是:

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations

用一个数组来存储所有的位置信息,如果需要查看前一个位置信息,则利用[locations lastObject]可以返回原来的oldLocation。

提一下CLLocation,这是管理位置的类,最基本的是由经度和纬度组成的。

我们可以计算两个经纬度之间的距离通过下面这个方法:

             (CLLocationDistance)distanceFromLocation:(const CLLocation *)location;

返回的是一个double类型的数据。


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:62836次
    • 积分:836
    • 等级:
    • 排名:千里之外
    • 原创:25篇
    • 转载:29篇
    • 译文:0篇
    • 评论:3条
    文章分类
    最新评论