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