Wednesday, 17 August 2016

Custom Map Annotation Pin in Swift

Custom Map Annotation Pin in Swift



1) Set Your Storyboard Like This :




2) Write This Code in ViewController :


import UIKit

import MapKit

private let reuseIdentifier = "CustomPin"

class ViewController: UIViewController, MKMapViewDelegate {

    @IBOutlet weak var mapView: MKMapView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
       
        let annotation = MKPointAnnotation()
        annotation.title = "My Home"
        annotation.coordinate = CLLocationCoordinate2D(latitude: 23.0300, longitude: 72.5800)

        self.mapView.addAnnotation(annotation)
        
        self.mapView.showAnnotations([annotation], animated: true)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView! {
        
        let pin = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseIdentifier) ?? CustomPin(annotation: annotation, reuseIdentifier:reuseIdentifier)
        
        pin.canShowCallout = false
        
        return pin
    }

    
    func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
        if let mapPin = view as? CustomPin {
            updatePinPosition(mapPin)
        }
    }
    
    func mapView(mapView: MKMapView, didDeselectAnnotationView view: MKAnnotationView) {
        
        if let mapPin = view as? CustomPin {
            if mapPin.preventDeselection {
                mapView.selectAnnotation(view.annotation!, animated: false)
                
                let alert = UIAlertController(title: "Alert", message: "View Clicked Here", preferredStyle: UIAlertControllerStyle.Alert)
                alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
                self.presentViewController(alert, animated: true, completion: nil)
                
            }
        }
    }
    
    func updatePinPosition(pin:CustomPin) {
        let defaultShift:CGFloat = 50
        let pinPosition = CGPointMake(pin.frame.midX, pin.frame.maxY)
        
        let y = pinPosition.y - defaultShift
        
        let controlPoint = CGPointMake(pinPosition.x, y)
        let controlPointCoordinate = mapView.convertPoint(controlPoint, toCoordinateFromView: mapView)
        
        mapView.setCenterCoordinate(controlPointCoordinate, animated: true)
    }
    

}


3) Create UIView XIB & Write This Code in UIVIEW Class :




CustomCallout.swift :

import Foundation

import MapKit

class CustomCallout: UIView {
    
    
    @IBOutlet weak var titleLabel: UILabel!
    
    override func hitTest(var point: CGPoint, withEvent event: UIEvent?) -> UIView? {
        let viewPoint = superview?.convertPoint(point, toView: self) ?? point
        
        let isInsideView = pointInside(viewPoint, withEvent: event)
        
        let view = super.hitTest(viewPoint, withEvent: event)
        
        return view
    }
    
    override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
        return CGRectContainsPoint(bounds, point)
    }
}


4) Create MKPinAnnotationView & Write This Code in MKPinAnnotationView Class :


import Foundation

import MapKit

class CustomPin: MKPinAnnotationView {
    
    private var calloutView:CustomCallout?
    private var hitOutside:Bool = true
    
    var preventDeselection:Bool {
        return !hitOutside
    }
    
    override func setSelected(selected: Bool, animated: Bool) {
        let calloutViewAdded = calloutView?.superview != nil
        
        
        if (selected || !selected && hitOutside) {
            super.setSelected(selected, animated: animated)
        }
        
        self.superview?.bringSubviewToFront(self)
        
        if (calloutView == nil) {
            calloutView = NSBundle.mainBundle().loadNibNamed("Callout", owner: nil, options: nil)[0] as? CustomCallout
            
            calloutView?.titleLabel.text = (self.annotation?.title)!
        }
        
        if (self.selected && !calloutViewAdded) {
            addSubview(calloutView!)
            calloutView!.center = CGPointMake(10, -calloutView!.frame.size.height / 2.0)
        }
        
        if (!self.selected) {
            calloutView?.removeFromSuperview()
        }
    }
    
    override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
        var hitView = super.hitTest(point, withEvent: event)
        
        if let callout = calloutView {
            if (hitView == nil && self.selected) {
                hitView = callout.hitTest(point, withEvent: event)
            }
        }
        
        hitOutside = hitView == nil
        
        return hitView;
    }
}



******* Finally OUTPUT : -









No comments:

Post a Comment