标签:
2:使用图片显示大头针视图,并使用自定义大头针模型、
3:自定义弹出视图、
4:适用于顶部title,底部自定义视图 ios9之后
代码部分:
class SecondViewController: UIViewController {
    lazy var mapView: MKMapView = {
        let mapView = MKMapView(frame:  UIScreen.mainScreen().bounds)
        mapView.mapType = .Standard
        mapView.scrollEnabled = true
        mapView.zoomEnabled = true
        mapView.showsUserLocation = true
        mapView.delegate = self
        return mapView
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(self.mapView)
        addAnnotations()
    }
    
    //MARK:  添加大头针
    func addAnnotations(){
        //创建MKPointAnnotation对象
        let pointAnnotation = MKPointAnnotation()
        pointAnnotation.coordinate = CLLocationCoordinate2DMake(39, 100)
        pointAnnotation.title = "Jack"
        pointAnnotation.subtitle = "hua"
        self.mapView.addAnnotation(pointAnnotation)
        
        //创建自定义大头针并添加到地图上
        let annotationOne = FirstAnnotation(coordinate:  CLLocationCoordinate2DMake(39, 115),title:"xxx大饭店",subtitle:"全场一律15折,会员20折")
        annotationOne.iconImage = UIImage(named: "boy")
        self.mapView.addAnnotation(annotationOne)
        
        //自定义弹出视图
        let calloutAnnotation = <span style="font-family: Menlo; font-variant-ligatures: no-common-ligatures;">SecondAnnotation</span><span style="font-family: 'PingFang SC';">(coordinate: CLLocationCoordinate2DMake(39, 80))</span>
        calloutAnnotation.icon = UIImage(named: "icon_classify_cafe")
        calloutAnnotation.rate = UIImage(named: "icon_Movie_Star_rating")
        calloutAnnotation.descriptionDetail = "This is a nice restaurant!I'm sure you will enjoy here!Come  to here,everone!"
        self.mapView.addAnnotation(calloutAnnotation)
        
        //使用系统自带附属视图
        let detailAnnotation = DetailCalloutAccessoryAnnotation(coordinate: CLLocationCoordinate2DMake(39, 90),title:"Jack")
        self.mapView.addAnnotation(detailAnnotation)
    }
}
代码分析:
上面代码主要是将地图添加到当前视图控制器视图上,并添加4个大头针到地图上,自定义大头针模型对象代码如下:
//自定义大头针模型
class FirstAnnotation: NSObject,MKAnnotation {
   
    //位置
    var coordinate: CLLocationCoordinate2D
    //主标题
    var title: String?
    //副标题
    var subtitle: String?
    //图片icon
    var iconImage: UIImage?
    init(coordinate: CLLocationCoordinate2D,title: String,subtitle:String) {
        self.coordinate = coordinate
        self.title = title
        self.subtitle = subtitle
        super.init()
    }
}
//用于弹出框类型判断模型
class SecondAnnotation: NSObject,MKAnnotation {
    
    //位置
    var coordinate: CLLocationCoordinate2D
    //左侧icon
    var icon: UIImage?
    //icon描述
    var descriptionDetail: String?
    //底部评分视图
    var rate: UIImage?
    init(coordinate: CLLocationCoordinate2D) {
        self.coordinate = coordinate
        super.init()
    }
}
//弹出视图模型
class SHCalloutAnnotation: NSObject,MKAnnotation{
    
    var coordinate: CLLocationCoordinate2D
    init(coordinate: CLLocationCoordinate2D) {
       self.coordinate = coordinate
       super.init()
    }
    //左侧icon
    var icon: UIImage?
    //icon描述
    var descriptionDetail: String?
    //底部评分视图
    var rate: UIImage?
}
//附属视图模型
class DetailCalloutAccessoryAnnotation: NSObject,MKAnnotation {
    
    //位置
    var coordinate: CLLocationCoordinate2D
    //主标题
    var title: String?
    //副标题
    var subtitle: String?    
    init(coordinate: CLLocationCoordinate2D,title: String) {
        self.coordinate = coordinate
        self.title = title
        super.init()
    }
    
    //官方示例代码使用:在模型中创建大头针视图
    class func createViewAnnotationForMapView(mapView:MKMapView, annotation:MKAnnotation) ->MKAnnotationView{
        let identifier = "DetailCalloutAccessoryAnnotation"
        var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)  as? MKPinAnnotationView
        if  (annotationView == nil){
            annotationView =  MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
            annotationView!.canShowCallout = true
            //设置大头针颜色
            annotationView!.pinColor = MKPinAnnotationColor.Purple
            
            let backgroundView = UIView(frame:  CGRectZero)
            backgroundView.backgroundColor = UIColor.redColor()
            //添加约束才可以使用自定义视图
            let widthConstraint = NSLayoutConstraint(item: backgroundView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 200)
            backgroundView.addConstraint(widthConstraint)
            let heightConstraint = NSLayoutConstraint(item: backgroundView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 200)
            backgroundView.addConstraint(heightConstraint)
            
            if #available(iOS 9.0, *) {
                //赋值UIImageView直接可以使用
                //returnAnnotaionView!.detailCalloutAccessoryView = UIImageView(image: UIImage(named: "icon_classify_cafe"))
                //直接赋值UIView,UILabel等视图不行?http://stackoverflow.com/questions/32581049/mapkit-ios-9-detailcalloutaccessoryview-usage 因为我们需要对宽和高做约束
                annotationView!.detailCalloutAccessoryView =  backgroundView
            } else {
                print("iOS9以下系统暂时不能够使用!")
            }
        }
        return annotationView!
    }
}
接下来,继续看一下视图控制器中的代码,我通过extension实现协议内容:
extension SecondViewController:MKMapViewDelegate{
    //显示大头针时调用,注意方法中的annotation参数是即将显示的大头针对象.1)该方法首先显示大头针的时候会调用2)向地图上添加大头针的时候也会调用
    func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
        
        var returnAnnotaionView:MKAnnotationView?
        if !(annotation.isKindOfClass(MKUserLocation)){//根据模型进行分类
            if annotation.isKindOfClass(MKPointAnnotation.self){
                //MARK:使用系统样式大头针视图和系统大头针模型
                let identifier = "MKPinAnnotationView"
                var returnAnnotaionView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
                if  (returnAnnotaionView == nil){
                    returnAnnotaionView =  MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
                    returnAnnotaionView!.canShowCallout = true
                    returnAnnotaionView!.calloutOffset = CGPoint(x: 0, y: -10)
                    returnAnnotaionView!.leftCalloutAccessoryView = UIButton(type: .ContactAdd)
                    returnAnnotaionView!.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure)
                }else{
                    returnAnnotaionView!.annotation = annotation
                }
                return returnAnnotaionView
            }else if annotation.isKindOfClass(FirstAnnotation.self){
                //MARK:使用图片显示大头针视图,并使用自定义大头针模型
                returnAnnotaionView = SHAnnotationView.annotationViewWith(mapView, reuseIdentifier:"SHAnnotationView")
                returnAnnotaionView!.annotation = annotation
                return returnAnnotaionView
            }else if annotation.isKindOfClass(SecondAnnotation.self){ 
                let identifier = "Annotation"
                var returnAnnotaionView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) as? MKPinAnnotationView
                if  (returnAnnotaionView == nil){
                    returnAnnotaionView =  MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
                    returnAnnotaionView!.pinColor = MKPinAnnotationColor.Green
                }
                 returnAnnotaionView!.annotation = annotation
                return returnAnnotaionView
            }else if annotation.isKindOfClass(SHCalloutAnnotation.self){
                //MARK:自定义弹出视图
                returnAnnotaionView = SHCalloutAnnotationView.calloutAnnotationViewWith(mapView) 
                returnAnnotaionView!.annotation = annotation
                return returnAnnotaionView
            }else if annotation.isKindOfClass(DetailCalloutAccessoryAnnotation.self){
                //MARK:适用于顶部title,底部自定义视图 ios9之后
                returnAnnotaionView = DetailCalloutAccessoryAnnotation.createViewAnnotationForMapView(mapView, annotation: annotation)
                returnAnnotaionView!.annotation = annotation
                return  returnAnnotaionView
            }
        }
        return returnAnnotaionView
    }
    
    //选中大头针时触发
    func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
        //点击大头针模型为SecondAnnotation时,添加自定义弹出视图的大头针到地图上。
        if let annotation = view.annotation{
            if(annotation.isKindOfClass(SecondAnnotation.self)){
            let annotation = annotation as! SecondAnnotation
            let calloutAnnotaion = SHCalloutAnnotation(coordinate: annotation.coordinate)
            calloutAnnotaion.icon = annotation.icon
            calloutAnnotaion.rate = annotation.rate
            calloutAnnotaion.descriptionDetail = annotation.descriptionDetail
            mapView.addAnnotation(calloutAnnotaion)
            }
        }
    }
    
    //反选时触发
    func mapView(mapView: MKMapView, didDeselectAnnotationView view: MKAnnotationView) {
        for annotation in self.mapView.annotations {
            if annotation.isKindOfClass(SHCalloutAnnotation.self){
                dispatch_async(dispatch_get_main_queue(), {
                    mapView.removeAnnotation(annotation)
                })
            }
        }
    }
}
以及自定义视图部分:
//边距
public let CalloutBorderSpace:CGFloat = 5
//MARK:自定义大头针视图
class SHAnnotationView: MKAnnotationView {
     
    class func annotationViewWith(mapView: MKMapView,reuseIdentifier:String) ->SHAnnotationView{
        //从缓存池中取出可以循环利用的大头针view
        var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseIdentifier) as? SHAnnotationView
        if annotationView == nil{
           annotationView = SHAnnotationView(annotation: nil, reuseIdentifier:reuseIdentifier)
           annotationView?.canShowCallout = true
           annotationView?.leftCalloutAccessoryView = UIButton(type: .InfoDark)
           annotationView?.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure)
        }
        return annotationView!
    }
    
    override var annotation: MKAnnotation?{
        didSet(annotation){
               //显示大头针为图片
            if let annotationOne = annotation as? FirstAnnotation{
               self.image = annotationOne.iconImage
            }
        }
    }
}
//MARK:弹出视图 继承于MKAnnotationView进行显示视图
class SHCalloutAnnotationView: MKAnnotationView{
    
    //#MARK:使用懒加载声明需要的控件属性
    lazy var leftIcon:UIImageView = {
         let leftIcon = UIImageView()
         self.addSubview(leftIcon)
         return leftIcon
    }()
    
    lazy var detailLabel:UILabel = {
         let detailLabel = UILabel(frame:  CGRectZero)
         detailLabel.lineBreakMode = .ByCharWrapping
         detailLabel.font = UIFont.systemFontOfSize(12)
         detailLabel.numberOfLines = 0
         self.addSubview(detailLabel)
         return detailLabel
    }()
    
    lazy var rateIcon:UIImageView = {
         let rateIcon = UIImageView()
         self.addSubview(rateIcon)
         return rateIcon
    }()
    
    var button:UIButton!
    
    //#MARK: 创建弹出视图
    class func calloutAnnotationViewWith(mapView: MKMapView)-> SHCalloutAnnotationView{
       let indentifier = "SHCallOutAnnotationView"
       var calloutView = mapView.dequeueReusableAnnotationViewWithIdentifier(indentifier) as? SHCalloutAnnotationView
       if calloutView == nil{
          calloutView = SHCalloutAnnotationView()
          calloutView!.backgroundColor = UIColor.grayColor()
       }
        return calloutView!
    }
    
    //#MARK:赋值数据模型显示相应的数据
    override var annotation: MKAnnotation?{
        
        didSet(callOutAnnotation){
            if let callOutAnnotation = callOutAnnotation as? SHCalloutAnnotation{
                self.leftIcon.image = callOutAnnotation.icon
                self.leftIcon.frame = CGRect(x: CalloutBorderSpace, y: CalloutBorderSpace, width: callOutAnnotation.icon!.size.width, height: callOutAnnotation.icon!.size.height)
                
                self.detailLabel.text = callOutAnnotation.descriptionDetail
                let string:NSString = self.detailLabel.text!
                let detailLabelSize = string.boundingRectWithSize(CGSize(width: 200,height: 200), options:.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: self.detailLabel.font], context: nil)
                self.detailLabel.frame = CGRect(x: CGRectGetMaxX(self.leftIcon.frame) + CalloutBorderSpace, y:CGRectGetMinY(self.leftIcon.frame), width: detailLabelSize.width, height: detailLabelSize.height)
                
                self.rateIcon.image = callOutAnnotation.rate
                self.rateIcon.frame = CGRect(x: CGRectGetMinX(self.detailLabel.frame), y: CGRectGetMaxY(self.detailLabel.frame) + CalloutBorderSpace, width: callOutAnnotation.rate!.size.width, height: callOutAnnotation.rate!.size.height)
                
                self.bounds = CGRect(x: 0, y: 0, width: CGRectGetMaxX(self.detailLabel.frame) + CalloutBorderSpace, height: CGRectGetMaxY(self.rateIcon.frame) + CalloutBorderSpace)
                
                //注意:确定最终的显示位置
                self.centerOffset = CGPointMake(0, -self.bounds.size.height)
            }
        }
    }
    //#MARK:当弹出视图显示的时候添加缩放动画
    override func didMoveToSuperview() {
            let animation = CAKeyframeAnimation(keyPath: "transform.scale")
            animation.values = [0,1.5,1,1.5,1]
            animation.duration = 0.5
            self.layer.addAnimation(animation, forKey: nil)
        }
}
代码分析:
我们之前已经添加了4个大头针到地图,当显示大头针的时候,会触发mapView(mapView:MKMapView, viewForAnnotation annotation:MKAnnotation)方法获取大头针视图,我们根据所添加的大头针模型进行分类返回对应的大头针视图。
对于显示使用系统样式大头针视图和系统大头针模型、使用图片显示大头针视图,并使用自定义大头针模型、ios9之后出现的附属视图的属性等都很简单,直接看代码就好。主要分析一下是如何实现callout视图的:
首先是添加一个大头针到视图上,当该大头针被点击的时候,添加我们自定义的大头针SecondAnnotation对象,所有数据都是源于原大头针模型,然后会触发mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation)方法,进行添加我们自定义的callout视图。并赋值annotation数据,显示整个视图。
实现效果图如下:
  
   
 
MapKit之大头针全面解析(使用系统大头针、自定义大头针callout视图、使用图片显示大头针)
标签:
原文地址:http://blog.csdn.net/longshihua/article/details/51720677