【iOS开发-111】自定义大头针Annotation以及2种导航划线的方法介绍

(1)自定义大头针Annotation的样式,也就是定义view,主要的方法是如下,传递一个大头针annotation模型,然后返回一个MKAnnotationView,这个MKAnnotationView有一个image属性,设置这个属性,就能设置它的样式了。

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
}

关键提示,这个MKAnnotationView和tableViewCell类似,可以循环利用,先从mapView中取,取不到再创建。

主要代码:

#import "ViewController.h"
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#import "WPAnnotation.h"

@interface ViewController ()<MKMapViewDelegate>
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
@property(nonatomic,strong) CLLocationManager *locMgr;
@end

@implementation ViewController

-(CLLocationManager *)locMgr{
    if (_locMgr==nil) {
        _locMgr=[[CLLocationManager alloc]init];
    }
    return _locMgr;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    if ([[UIDevice currentDevice].systemVersion doubleValue]>=8.0) {
        [self.locMgr requestWhenInUseAuthorization];
    }
    //设置代理
    self.mapView.delegate=self;
    //添加两个大头针
    WPAnnotation *anno0=[[WPAnnotation alloc]init];
    anno0.coordinate=CLLocationCoordinate2DMake(40, 116);
    [email protected]"全聚德";
    [email protected]"全北京最好的烤鸭店";
    [email protected]"category_1";
    [self.mapView addAnnotation:anno0];

    WPAnnotation *anno1=[[WPAnnotation alloc]init];
    anno1.coordinate=CLLocationCoordinate2DMake(39, 115);
    [email protected]"万达影院";
    [email protected]"全中国最顶尖的观影圣地";
    [email protected]"category_5";
    [self.mapView addAnnotation:anno1];
}

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
    static NSString *[email protected]"annoView";
    MKAnnotationView *annoView=[mapView dequeueReusableAnnotationViewWithIdentifier:ID];
    if (annoView==nil) {
        annoView=[[MKAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:ID];
        //点击大头针出现信息(自定义view的大头针默认点击不弹出)
        annoView.canShowCallout=YES;
    }
    //再传递一次annotation模型(赋值)
    annoView.annotation=annotation;

    WPAnnotation *anno=annotation;
    annoView.image=[UIImage imageNamed:anno.icon];

    return annoView;
}

@end

大头针模型,多了一个icon属性,因为我们要自定义大头针,所以需要图形属性:

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface WPAnnotation : NSObject<MKAnnotation>
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;
//自定义大头针图片
@property(nonatomic,copy) NSString *icon;
@end

(2)如果我们加入追踪用户现有位置时

//追踪用户位置
self.mapView.userTrackingMode=MKUserTrackingModeFollow;

发现会有如下报错:[MKUserLocation icon]: unrecognized selector sent to instance 0x7f89baecab50

主要原因是,追踪用户位置的MKUserLocation也是一个大头针(蓝色发光的那个圈圈),它也要经过viewForAnnotation这个代理方法返回自定义的大头针,但是它是没有icon属性的,所以报错。我们应该在viewForAnnotation中添加一个判断:

//如果是系统自带的大头针,则返回默认的,否则下面要设置icon时会报错,因为系统的大头针没有icon属性
if (![annotation isKindOfClass:[WPAnnotation class]]) return nil;

(3)还有一个MKPinAnnotationView是MKAnnotationView的子类,属性多2个,一个是设置颜色,就是可以设置大头针的颜色,还有一个是设置大头针从天而降。

- (void)viewDidLoad {
    [super viewDidLoad];
    ......
    [self.mapView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapMapView:)]];
}

-(void)tapMapView:(UITapGestureRecognizer *)tap{
    //获取点
    CGPoint point=[tap locationInView:tap.view];
    //点转坐标
    CLLocationCoordinate2D coordi=[self.mapView convertPoint:point toCoordinateFromView:self.mapView];
    WPAnnotation *anno=[[WPAnnotation alloc]init];
    anno.coordinate=coordi;
    [email protected]"全聚德";
    [email protected]"来一只鸭子,老板!";
    [self.mapView addAnnotation:anno];
}

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
    static NSString *[email protected]"map";
    MKPinAnnotationView *annoView=(MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:ID];
    if (annoView==nil) {
        annoView=[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:ID];
        //设置描述信息能点击出现
        annoView.canShowCallout=YES;
        //设置颜色
        annoView.pinColor=MKPinAnnotationColorGreen;
        //设置第一次出现从天而降
        annoView.animatesDrop=YES;
    }
    return annoView;
}

(4)自定义一个MKAnnotationView,并利用代理方法,监听大头针的点击,点击后,再弹出一个“大头针”(只不过这个大头针是自定义MkAnnotationView的)。

我们一般返回一个大头针视图,用下面这个类似于tableViewCell的方法。

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
    if ([annotation isKindOfClass:[WPDescriptionAnnotation class]]) {
        WPAnnotationView *annoView=[WPAnnotationView annotationWithMapView:mapView];
        annoView.annotation=annotation;
        return annoView;
    }else if ([annotation isKindOfClass:[WPAnnotation class]]){
        WPTuanGouAnnotationView *annoView=[WPTuanGouAnnotationView annotationWithMapView:mapView];
        annoView.annotation=annotation;
        return annoView;
    }
    return nil;
}

点击某一个大头针视图,也类似于点击tableView的某一行(这里有一些判断语句十分实用):

//点击大头针,弹出一个自定义的大头针充当描述信息
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
    if (![view isKindOfClass:[WPTuanGouAnnotationView class]]) return;
    //删除所有再添加,保证只有1个,也防止重复
    for (id annotation in mapView.annotations) {
        if ([annotation isKindOfClass:[WPDescriptionAnnotation class]]) {
            [mapView removeAnnotation:annotation];
        }
    }
    WPAnnotation *anno=view.annotation;
    WPDescriptionAnnotation *descAnno=[[WPDescriptionAnnotation alloc]init];
    descAnno.tuangou=anno.tuangou;
    [mapView addAnnotation:descAnno];
}

我们一般在项目中添加大头针,是有数据模型的。先把这个数据模型赋值给大头针,然后再添加。当然,大头针需要在自己的类中设置setTuangou也就是设置数据模型。

for (WPTuanGou *tuan in self.tuangous) {
        WPAnnotation *anno=[[WPAnnotation alloc]init];
        anno.tuangou=tuan;
        [self.mapView addAnnotation:anno];
}

我们一般在项目中,都是把模型和大头针,当做参数在不同的对象之间传递。

(5)导航划线

#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#import "WPAnnotation.h"

@interface ViewController ()<MKMapViewDelegate>
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
@property(nonatomic,strong) CLGeocoder *geocoder;

@end

@implementation ViewController

-(CLGeocoder *)geocoder{
    if (_geocoder==nil) {
        _geocoder=[[CLGeocoder alloc]init];
    }
    return _geocoder;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.mapView.delegate=self;

    NSString *[email protected]"广州";
    NSString *[email protected]"北京";
    //这个方法只能生效1个,所以不能分开写
    [self.geocoder geocodeAddressString:add1 completionHandler:^(NSArray *placemarks, NSError *error) {
        if (error) return;
        CLPlacemark *fromPm=[placemarks firstObject];
        [self.geocoder geocodeAddressString:add2 completionHandler:^(NSArray *placemarks, NSError *error) {
            CLPlacemark *toPm=[placemarks firstObject];
            [self addLineFrom:fromPm to:toPm];
        }];
    }];
}

-(void)addLineFrom:(CLPlacemark *)fromPm to:(CLPlacemark *)toPm{
    //添加2个大头针
    WPAnnotation *anno0=[[WPAnnotation alloc]init];
    anno0.coordinate=fromPm.location.coordinate;
    [self.mapView addAnnotation:anno0];

    WPAnnotation *anno1=[[WPAnnotation alloc]init];
    anno1.coordinate=toPm.location.coordinate;
    [self.mapView addAnnotation:anno1];

    //设置方向请求
    MKDirectionsRequest *request=[[MKDirectionsRequest alloc]init];
    //设置起点终点
    MKPlacemark *sourcePm=[[MKPlacemark alloc]initWithPlacemark:fromPm];
    request.source=[[MKMapItem alloc]initWithPlacemark:sourcePm];
    MKPlacemark *destiPm=[[MKPlacemark alloc]initWithPlacemark:toPm];
    request.destination=[[MKMapItem alloc]initWithPlacemark:destiPm];
    //定义方向对象
    MKDirections *dirs=[[MKDirections alloc]initWithRequest:request];
    //计算路线
    [dirs calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
        NSLog(@"总共有%lu条线路",(unsigned long)response.routes.count);
        for (MKRoute *route in response.routes) {
            [self.mapView addOverlay:route.polyline];
        }
    }];
}

//划线就是添加路径,就是添加遮盖
-(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{
    MKPolylineRenderer *renderer=[[MKPolylineRenderer alloc]initWithOverlay:overlay];
    renderer.strokeColor=[UIColor redColor];
    return renderer;
}

@end

还有一种方式创建导航,即利用MKMapItem:

    MKMapItem *from=[[MKMapItem alloc]initWithPlacemark:[[MKPlacemark alloc] initWithPlacemark:fromPm]];
    MKMapItem *to=[[MKMapItem alloc]initWithPlacemark:[[MKPlacemark alloc] initWithPlacemark:toPm]];
    NSMutableDictionary *options=[NSMutableDictionary dictionary];
    options[MKLaunchOptionsDirectionsModeKey]=MKLaunchOptionsDirectionsModeDriving;
    options[MKLaunchOptionsShowsTrafficKey][email protected];
    [MKMapItem openMapsWithItems:@[from,to] launchOptions:options];
时间: 2024-08-25 07:48:05

【iOS开发-111】自定义大头针Annotation以及2种导航划线的方法介绍的相关文章

iOS开发之自定义表情键盘(组件封装与自动布局)

下面的东西是编写自定义的表情键盘,话不多说,开门见山吧!下面主要用到的知识有MVC, iOS开发中的自动布局,自定义组件的封装与使用,Block回调,CoreData的使用.有的小伙伴可能会问写一个自定义表情键盘肿么这么麻烦?下面将会介绍我们如何用上面提到的东西来定义我们的表情键盘的.下面的内容会比较多,这篇博文还是比较有料的. 还是那句话写技术博客是少不了代码的,下面会结合代码来回顾一下iOS的知识,本篇博文中用到的知识点在前面的博客中都能找到相应的内容,本篇算是一个小小的功能整合.先来张图看

iOS开发中自定义字体的方法

http://www.cnblogs.com/iyou/archive/2014/05/25/3751669.html 1. 首先下载你想要设置的字体库,例如设置方正启体简体 2. 添加到工程,一定要注意勾选红色框框处,默认是不勾选的  添加以后 3.在plist文件中添加 4.现在已经添加成功了,但是要使用就必须知道FontName,用以下代码可查到 NSArray *familyNames = [[NSArray alloc] initWithArray:[UIFont familyName

详解iOS开发之自定义View

iOS开发之自定义View是本文要将介绍的内容,iOS SDK中的View是UIView,我们可以很方便的自定义一个View.创建一个 Window-based Application程序,在其中添加一个Hypnosister的类,这个类选择继承UIObject.修改这个类,使他继承:UIView @interface HypnosisView : UIView 自定义View的关键是定义drawRect: 方法,因为主要是通过重载这个方法,来改变view的外观.例如,可以使用下面代码绘制一个很

IOS开发之自定义系统弹出键盘上方的view

IOS开发之自定义系统弹出键盘上方的view 分类: IOS 2014-11-18 09:26 1304人阅读 评论(0) 收藏 举报 目录(?)[+] 这篇文章解决的一个开发中的实际问题就是:当弹出键盘时,自定义键盘上方的view.目前就我的经验来看,有两种解决方法.一个就是利用 UITextField或者UITextView的inputAccessoryView属性,另一种,就是监听键盘弹出的notification来自 己解决相关视图的位置问题. 第一种解决方法相对比较简单,第二种的方法中

ios开发中object-c中UTF-8 和 GBK 的 NSString 相互转化的方法

应用都要遇到一个很头疼的问题:文字编码,汉字的 GBK 和 国际通用的 UTF-8 的互相转化稍一不慎, 就会满屏乱码.下面介绍 UTF-8 和 GBK 的 NSString 相互转化的方法 NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000); char* c_test = "北京"; int nLen = strlen(c_test); NSS

iOS 地图中自定义大头针

1.继承MKAnnotationView. HYAnnotationView.h文件: + (instancetype)annotationViewWithMapView:(MKMapView *)mapView; HYAnnotationView.m文件: #import "HYAnnotation.h"//导入大头针model的头文件 @interface HYAnnotationView() @property (nonatomic, weak) UIImageView *ico

【Swift】IOS开发中自定义转场动画

在IOS开发中,我们model另外一个控制器的时候,一般都使用的自定义的转场动画. 其实我们可以自定义一些转场动画.达到不同的转场效果. 步骤如下:(photoBrowser是目标控制器) 1.在源控制器中,设置目标控制器的转场代理为 self 1 //设置Model转场代理 2  photoBrowser.transitioningDelegate = self 2.同时设置目标控制器的model类型 1 //设置Model类型 2 photoBrowser.modalPresentation

iOS开发 - 使用自定义字体

上次有个同事问我,XXapp的字体怎么那么萌啊?我也想要搞个萌哒哒的字体!于是,就有了今天这篇blog. 首先,我们在iOS开发中,苹果给我们提供了许多的字体,当然这里我就不列举啦,都是些英文,小汤表示看不懂啦,我要自己搞萌萌哒的字体啊啊啊啊!!! 比如说这样的: 又比如说这样的: 好了,回归正题,上面卖萌的绝对不是作者君啦. 那天,作者君从网上下载了一个ttf的字体如下: 然后小汤我非常淡定的执行了下面这段代码: UILabel *label = [[UILabel alloc]initWit

iOS开发中自定义相册功能性能改善

大多数项目中都会用到相册浏览和选择功能,如果需要使用到自定义相册浏览器,那么,性能优化将是一个很重要的课题.毕竟操作对象是图片这样相对较大写数据单位.今天就针自定义相册浏览选择器四个优化点进行剖析: 缩略图页面加载速度优化 缩略图页面滑动流畅度优化 大图浏览滑动流畅度优化 内存优化 先看看自定义相册的两个主要界面: 1.缩略图页面加载速度优化 如果本地相册有200张以上的照片,那么缩略图页面的加载速度就显得尤为重要. 首先,要保证缩略图界面的控制器在没有加载照片的时候,从viewDidLoad到