Reputation: 387
I am new to iOS development and I need to implement a draggable annotation in iOS maps. my code is given below.whater ever I do I can't get a draggable annotation can anyone help with the annotations after that I need to get address of the location where the pin is pointing
RegistrationViewController.swift
class RegistrationViewController: UIViewController,UIPickerViewDelegate,UIPickerViewDataSource,MKMapViewDelegate{
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
var centerLocation = CLLocationCoordinate2DMake(12.964370125970357, 77.59643554937497)
var mapspan = MKCoordinateSpanMake(0.01, 0.01)
var mapregion = MKCoordinateRegionMake(centerLocation, mapspan)
self.mapView.setRegion(mapregion, animated: true)
let pin = pinAnnotation(title:"hello",subtitle:"how are you",coordinate:centerLocation)
mapView.addAnnotation(pin)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if annotation is MKPointAnnotation {
let pinAnnotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "myPin")
pinAnnotationView.pinColor = .purple
pinAnnotationView.isDraggable = true
pinAnnotationView.canShowCallout = true
pinAnnotationView.animatesDrop = true
return pinAnnotationView
}
return nil
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, didChange newState: MKAnnotationViewDragState, fromOldState oldState: MKAnnotationViewDragState) {
switch newState {
case .starting:
view.dragState = .dragging
case .ending, .canceling:
view.dragState = .none
default: break
}
}
pinAnnotation.swift
import MapKit
class pinAnnotation:NSObject,MKAnnotation {
var title:String?
var subtitle: String?
var coordinate: CLLocationCoordinate2D
init(title:String,subtitle:String,coordinate:CLLocationCoordinate2D) {
self.title = title
self.subtitle = subtitle
self.coordinate = coordinate
}
}
Upvotes: 4
Views: 2002
Reputation: 71852
In your case annotation
is not an MKPointAnnotation
type. Thats why its not entering into if annotation is MKPointAnnotation {
condition.
It should be like:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is pinAnnotation {
let pinAnnotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "myPin")
pinAnnotationView.pinTintColor = .purple
pinAnnotationView.isDraggable = true
pinAnnotationView.canShowCallout = true
pinAnnotationView.animatesDrop = true
return pinAnnotationView
}
return nil
}
Because annotation
is pinAnnotation
type.
And I can not see mapView.delegate = self
in your code. But if you assign it via storyboard thats fine otherwise add it in viewDidLoad
method.
And your complete code will be:
import UIKit
import MapKit
class ViewController: UIViewController,MKMapViewDelegate{
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
let centerLocation = CLLocationCoordinate2D(latitude: 12.964370125970357, longitude: 77.59643554937497)
let mapspan = MKCoordinateSpanMake(0.01, 0.01)
let mapregion = MKCoordinateRegionMake(centerLocation, mapspan)
self.mapView.setRegion(mapregion, animated: true)
let pin = pinAnnotation(title:"hello",subtitle:"how are you",coordinate:centerLocation)
mapView.addAnnotation(pin)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is pinAnnotation {
let pinAnnotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "myPin")
pinAnnotationView.pinTintColor = .purple
pinAnnotationView.isDraggable = true
pinAnnotationView.canShowCallout = true
pinAnnotationView.animatesDrop = true
return pinAnnotationView
}
return nil
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, didChange newState: MKAnnotationViewDragState, fromOldState oldState: MKAnnotationViewDragState) {
switch newState {
case .starting:
view.dragState = .dragging
case .ending, .canceling:
view.dragState = .none
default: break
}
}
}
EDIT
You can get new location with view.annotation?.coordinate
check below code:
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, didChange newState: MKAnnotationViewDragState, fromOldState oldState: MKAnnotationViewDragState) {
switch newState {
case .starting:
view.dragState = .dragging
case .ending, .canceling:
//New cordinates
print(view.annotation?.coordinate)
view.dragState = .none
default: break
}
}
Upvotes: 5
Reputation: 1996
You have the first step done by setting the isDraggable
property to true.
Now you only need to handle when the user stops dragging and drops the annotation, see:
how to manage drag and drop for MKAnnotationView on IOS
Besides, your pinAnnotation should have a settable coordinates.
From Apple documentation:
Marking Your Annotation View as Draggable Annotation views provide built-in dragging support, which makes it very easy to drag annotations around the map and to ensure that the annotation data is updated accordingly. To implement minimal support for dragging:
In your annotation objects, implement the setCoordinate: method to allow the map view to update the annotation’s coordinate point. When creating your annotation view, set its draggable property to YES. When the user touches and holds a draggable annotation view, the map view begins a drag operation for it. As the drag operation progresses, the map view calls the mapView:annotationView:didChangeDragState:fromOldState: method of its delegate to notify it of changes to the drag state of your view. You can use this method to affect or respond to the drag operation.
To animate your view during a drag operation, implement a custom dragState method in your annotation view. As the map view processes drag-related touch events, it updates the dragState property of the affected annotation view. Implementing a custom dragState method gives you a chance to intercept these changes and perform additional actions, such as animating the appearance of your view. For example, the MKPinAnnotationView class raises the pin off the map when a drag operation starts and drops the pin back down on the map when it ends.
You are missing the mapView:annotationView:didChangeDragState:fromOldState:
method
Upvotes: 2