determine if MKMapView was dragged/moved
Asked Answered
D

19

92

Is there a way to determine if a MKMapView was dragged around?

I want to get the center location every time a user drags the map using CLLocationCoordinate2D centre = [locationMap centerCoordinate]; but I'd need a delegate method or something that fires as soon as the user navigates around with the map.

Durham answered 5/4, 2011 at 18:54 Comment(0)
J
18

Look at the MKMapViewDelegate reference.

Specifically, these methods may be useful:

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated

Make sure your map view's delegate property is set so those methods get called.

Jaquesdalcroze answered 5/4, 2011 at 19:10 Comment(7)
Thanks a lot. - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated did the job.Durham
Great solution. Perfect to reload annotations on the map when user changes locationDockage
-1 because this solution does not tell you if the user dragged the map. The regionWillChangeAnimated happens if the user rotates the device or another method zooms the map, not necessarily in response to dragging.Pensile
Thanks @Pensile I found the same problem with this 'answer'Taryn
@mobi 's solution detects user gestures (yes, all of them) by checking on mapviews internal gesture recognizers. Nice!Coeternal
It doesn't answer the question. And, sometimes it doesn't solve the problem. Like: If the map will change region automatically, we don't wanna trigger irrelevant issue.Reginareginald
This does not answer the question. The person needs to know if the user dragged it. This just shows when the map moves (ie, an animation done programmatically)Gentlefolk
A
242

The code in the accepted answer fires when the region is changed for any reason. To properly detect a map drag you have to add a UIPanGestureRecognizer. Btw, this is the drag gesture recognizer (panning = dragging).

Step 1: Add the gesture recognizer in viewDidLoad:

-(void) viewDidLoad {
    [super viewDidLoad];
    UIPanGestureRecognizer* panRec = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didDragMap:)];
    [panRec setDelegate:self];
    [self.mapView addGestureRecognizer:panRec];
}

Step 2: Add the protocol UIGestureRecognizerDelegate to the view controller so it works as delegate.

@interface MapVC : UIViewController <UIGestureRecognizerDelegate, ...>

Step 3: And add the following code for the UIPanGestureRecognizer to work with the already existing gesture recognizers in MKMapView:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}

Step 4: In case you want to call your method once instead 50 times per drag, detect that "drag ended" state in your selector:

- (void)didDragMap:(UIGestureRecognizer*)gestureRecognizer {
    if (gestureRecognizer.state == UIGestureRecognizerStateEnded){
        NSLog(@"drag ended");
    }
}
Aret answered 26/7, 2012 at 18:22 Comment(9)
I know this is a fairly old post but I love your idea above, i struggled organising my app with the regionDidChange method on its own with my implementation and when I saw this it all clicked and you are so right that regionDidChange fires for any reason which is not ideal with this I can get may map to do exactly what I want so Kudos for this!Condign
This is a much more reliable solution than mapView:regionDidChangeAnimated:, which is called if the map's region is programmatically changed (in my case I only want to know if the user manually scrolls the map). Thanks for posting!Justinejustinian
If you want to catch pinches too, you'll want to add a UIPinchGestureRecognizer as wellFula
Note that the map view scroll carries momentum, and the above example will be fired off as soon as the gesture ends but before the map view stops moving. There may be a better way, but what I've done is set a flag when the gesture stops, readyForUpdate, and then check that flag in - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated.Octamerous
Note that the user can double tap a single or two fingers to zoom, which will change the region but wont call this pan recognizer.Deckert
Is this the best way to handle this? I want to check what the center coordinate is MKMapView every time the map gets draggedHaemo
@mobi 's solution is simpler and seems to catch ALL gestures plus no problems with momentum. Works great for me.Coeternal
Why is this solution at the bottom? It's the best one! Yes @mobi 's solution is simpler but this one is safer.Henhouse
This is not the best answer as it does not really cover all the potential cases such as pinching or touching.Chicle
M
79

This is the only way that worked for me that detects pan as well as zoom changes initiated by user:

- (BOOL)mapViewRegionDidChangeFromUserInteraction
{
    UIView *view = self.mapView.subviews.firstObject;
    //  Look through gesture recognizers to determine whether this region change is from user interaction
    for(UIGestureRecognizer *recognizer in view.gestureRecognizers) {
        if(recognizer.state == UIGestureRecognizerStateBegan || recognizer.state == UIGestureRecognizerStateEnded) {
            return YES;
        }
    }

    return NO;
}

static BOOL mapChangedFromUserInteraction = NO;

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
    mapChangedFromUserInteraction = [self mapViewRegionDidChangeFromUserInteraction];

    if (mapChangedFromUserInteraction) {
        // user changed map region
    }
}

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    if (mapChangedFromUserInteraction) {
        // user changed map region
    }
}
Michalemichalski answered 23/9, 2014 at 18:25 Comment(3)
This works for me, but it should be noted that this is dependent on the internal implementation of MKMapView in iOS. That implementation could change in any iOS update since it is not part of the API.Thorvald
This works, and I like it better than the leading answer because it doesn't alter what's there.Ingrained
Thanks for the elegant solution of code vs. user map manipulation.Unprecedented
L
32

(Just the) Swift version of @mobi's excellent solution:

private var mapChangedFromUserInteraction = false

private func mapViewRegionDidChangeFromUserInteraction() -> Bool {
    let view = self.mapView.subviews[0]
    //  Look through gesture recognizers to determine whether this region change is from user interaction
    if let gestureRecognizers = view.gestureRecognizers {
        for recognizer in gestureRecognizers {
            if( recognizer.state == UIGestureRecognizerState.Began || recognizer.state == UIGestureRecognizerState.Ended ) {
                return true
            }
        }
    }
    return false
}

func mapView(mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
    mapChangedFromUserInteraction = mapViewRegionDidChangeFromUserInteraction()
    if (mapChangedFromUserInteraction) {
        // user changed map region
    }
}

func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
    if (mapChangedFromUserInteraction) {
        // user changed map region
    }
}
Liles answered 18/6, 2015 at 20:4 Comment(3)
Looks good, but I had to change self.mapView.subviews[0] to self.mapView.subviews[0] as! UIViewCense
This (and moby's) solution is not so excellent. There is no guarantee that Apple will preserve mapViews first subview. Maybe at some future version, mapView's first subView won't be a UIView. So your code is not crash repellent. Try to add your own GestureRecognizers to MapView.Equate
note, to get this working I had to add self.map.delegate = self to viewDidLoadTamberg
S
20

Swift 3 solution to Jano's answer above:

Add the Protocol UIGestureRecognizerDelegate to your ViewController

class MyViewController: UIViewController, UIGestureRecognizerDelegate

Create the UIPanGestureRecognizer in viewDidLoad and set delegate to self

viewDidLoad() {
    // add pan gesture to detect when the map moves
    let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.didDragMap(_:)))

    // make your class the delegate of the pan gesture
    panGesture.delegate = self

    // add the gesture to the mapView
    mapView.addGestureRecognizer(panGesture)
}

Add a Protocol method so your gesture recognizer will work with the existing MKMapView gestures

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}

Add the method that will be called by the selector in your pan gesture

func didDragMap(_ sender: UIGestureRecognizer) {
    if sender.state == .ended {

        // do something here

    }
}
Shirlyshiroma answered 14/12, 2016 at 20:25 Comment(1)
Thiss is the solution! Thanks!Choler
J
18

Look at the MKMapViewDelegate reference.

Specifically, these methods may be useful:

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated

Make sure your map view's delegate property is set so those methods get called.

Jaquesdalcroze answered 5/4, 2011 at 19:10 Comment(7)
Thanks a lot. - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated did the job.Durham
Great solution. Perfect to reload annotations on the map when user changes locationDockage
-1 because this solution does not tell you if the user dragged the map. The regionWillChangeAnimated happens if the user rotates the device or another method zooms the map, not necessarily in response to dragging.Pensile
Thanks @Pensile I found the same problem with this 'answer'Taryn
@mobi 's solution detects user gestures (yes, all of them) by checking on mapviews internal gesture recognizers. Nice!Coeternal
It doesn't answer the question. And, sometimes it doesn't solve the problem. Like: If the map will change region automatically, we don't wanna trigger irrelevant issue.Reginareginald
This does not answer the question. The person needs to know if the user dragged it. This just shows when the map moves (ie, an animation done programmatically)Gentlefolk
A
8

In my experience, similar to "search while typing", I found a timer is the most reliable solution. It removes the need for adding additional gesture recognizers for panning, pinching, rotating, tapping, double tapping, etc.

The solution is simple:

  1. When the map region changes, set/reset the timer
  2. When the timer fires, load markers for the new region

    import MapKit
    
    class MyViewController: MKMapViewDelegate {
    
        @IBOutlet var mapView: MKMapView!
        var mapRegionTimer: NSTimer?
    
        // MARK: MapView delegate
    
        func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
            setMapRegionTimer()
        }
    
        func setMapRegionTimer() {
            mapRegionTimer?.invalidate()
            // Configure delay as bet fits your application
            mapRegionTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "mapRegionTimerFired:", userInfo: nil, repeats: false)
        }
    
        func mapRegionTimerFired(sender: AnyObject) {
            // Load markers for current region:
            //   mapView.centerCoordinate or mapView.region
        }
    
    }
    
Amyl answered 29/2, 2016 at 19:59 Comment(0)
E
8

A lot of these solutions are on the hacky / not what Swift intended side, so I opted for a cleaner solution.

I simply subclass MKMapView and override touchesMoved. While this snippet does not include it, I would recommend creating a delegate or notification to pass on whatever information you want regarding the movement.

import MapKit

class MapView: MKMapView {
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesMoved(touches, with: event)

        print("Something moved")
    }
}

You will need to update the class on your storyboard files to point to this subclass, as well as modify any maps you create through other means.

As noted in the comments, Apple discourages the use of subclassing MKMapView. While this falls to the discretion of the developer, this particular usage does not modify the behavior of the map & has worked for me without incident for over three years. However, past performance does not indicate future compatibility, so caveat emptor.

Edulcorate answered 12/1, 2017 at 22:3 Comment(3)
This seems like the best solution. I've tested it and is seems to work ok. I think is good for others to be aware that Apple advises to not subclass MKMapView: "Although you should not subclass the MKMapView class itself, you can get information about the map view’s behavior by providing a delegate object." Link: developer.apple.com/documentation/mapkit/mkmapview . However I don't have a strong opinion about ignoring their advice to not subclass MKMapView and I'm open to learn more from others regarding this.Leer
"This seems like the best solution even though Apple says don't do it" seems like maybe it's not the best solution.Shirlyshiroma
This works for me since I am subclassing map already for some other reasons. I am aware that Apple recommends (does not forbid) MKMapView subclassing, relying on internal Apple's UIView implementation or even implementing all kinds of gesture recognisers just to detect users activity seems much worse approach to me.Silvery
P
7

Another possible solution is to implement touchesMoved: (or touchesEnded:, etc.) in the view controller that holds your map view, like so:

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesMoved:touches withEvent:event];

    for (UITouch * touch in touches) {
        CGPoint loc = [touch locationInView:self.mapView];
        if ([self.mapView pointInside:loc withEvent:event]) {
            #do whatever you need to do
            break;
        }
    }
}

This might be simpler than using gesture recognizers, in some cases.

Pressman answered 1/8, 2014 at 19:43 Comment(0)
P
6

You can also add a gesture recognizer to your map in Interface Builder. Link it up to an outlet for its action in your viewController, I called mine "mapDrag"...

Then you'll do something like this in your viewController's .m:

- (IBAction)mapDrag:(UIPanGestureRecognizer *)sender {
    if(sender.state == UIGestureRecognizerStateBegan){
        NSLog(@"drag started");
    }
}

Make sure you have this there too:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}

Of course you'll have to make your viewController a UIGestureRecognizerDelegate in your .h file in order for that to work.

Otherwise the map's responder is the only one who hears the gesture event.

Pensile answered 28/1, 2014 at 2:26 Comment(1)
perfect for storyboard solution. Nice job with UIGestureRecognizerStateBeganTa
S
5

To recognize when any gesture ended on the mapview:

[https://web.archive.org/web/20150215221143/http://b2cloud.com.au/tutorial/mkmapview-determining-whether-region-change-is-from-user-interaction/)

This is very useful for only performing a database query after the user is done zooming/rotating/dragging the map around.

For me, the regionDidChangeAnimated method only was called after the gesture was done, and didn't get called many times while dragging/zooming/rotating, but it's useful to know if it was due to a gesture or not.

Selmaselman answered 27/5, 2015 at 3:45 Comment(2)
web.archive.org/web/20150215221143/http://b2cloud.com.au/…Selmaselman
This method did not worked for me. As soon as mapView region changes from code it triggers that it was from user ...Repetition
T
5

I know this is an old post but here my Swift 4/5 code of Jano's answer whit Pan and Pinch gestures.

class MapViewController: UIViewController, MapViewDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.didDragMap(_:)))
        let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(self.didPinchMap(_:)))
        panGesture.delegate = self
        pinchGesture.delegate = self
        mapView.addGestureRecognizer(panGesture)
        mapView.addGestureRecognizer(pinchGesture)
    }

}

extension MapViewController: UIGestureRecognizerDelegate {

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }

    @objc func didDragMap(_ sender: UIGestureRecognizer) {
        if sender.state == .ended {
            //code here
        }
    }

    @objc func didPinchMap(_ sender: UIGestureRecognizer) {
        if sender.state == .ended {
            //code here
        }
    }
}

Enjoy!

Tumpline answered 4/8, 2019 at 11:8 Comment(1)
As said earlier this doesn't recognize zooms but it should be Good Enough™ for most.Fenestration
C
4

You can check for animated property if false then user dragged map

 func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
    if animated == false {
        //user dragged map
    }
}
Chromatolysis answered 6/8, 2018 at 10:8 Comment(2)
User could have zoomed map.Johannisberger
cute, but does not distinct user interaction from programmatically region change, tested on iOS 14.Silvery
B
3

Jano's answer worked for me, so I thought I'd leave an updated version for Swift 4 / XCode 9 as I'm not particularly proficient in Objective C and I'm sure there are a few others that aren't either.

Step 1: Add this code in viewDidLoad:

let panGesture = UIPanGestureRecognizer(target: self, action: #selector(didDragMap(_:)))
panGesture.delegate = self

Step 2: Make sure your class conforms to the UIGestureRecognizerDelegate:

class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate, UIGestureRecognizerDelegate {

Step 3: Add the following function to make sure your panGesture will work simultaneously with other gestures:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}

Step 4: And ensuring your method isn't called "50 times per drag" as Jano rightly points out:

@objc func didDragMap(_ gestureRecognizer: UIPanGestureRecognizer) {
    if (gestureRecognizer.state == UIGestureRecognizerState.ended) {
        redoSearchButton.isHidden = false
        resetLocationButton.isHidden = false
    }
}

*Note the addition of @objc in the last step. XCode will force this prefix on your function in order for it compile.

Botanomancy answered 8/2, 2018 at 2:29 Comment(0)
D
2

@Joshua Hart had an elegant solution, however I modified it to be used with SwiftUI's UIViewRepresentable coordinator. All you need to do is to tellit specifically what gestureState that your parent SwiftUI view is looking for.

2023, iOS 16+ , SwiftUI Coordinator Implementation

class Coordinator: NSObject, MKMapViewDelegate {
        let parent: MapView
        var workItem: DispatchWorkItem?

        /// Obtains all gestures within the mapView subviews to see if any
        /// of the gestures changed state to began or ended.
        /// - Returns: True if any gesture within the mapView changed state to ended, false otherwise.
        private func regionDidChangeFromUserInteraction(_ mapView: MKMapView, gestureState: UIGestureRecognizer.State) -> Bool {
            mapView.subviews// Look at all mapView subviews
                .compactMap { $0.gestureRecognizers } // look at all subview gesture recognizers
                .reduce([], +) // Reduces an Array of Arrays of gestures to an Array of gestures
                .contains(where: { $0.state == gestureState }) // if ended returns true else false
        }

        /// The framework calls this method at the beginning of a change to the map’s visible region.
        func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
            guard regionDidChangeFromUserInteraction(mapView, gestureState: .changed) else {
                print("mapView:regionWillChangeAnimated - No Interaction detected.")
                return
            }
            print("mapView:regionWillChangeAnimated - User Interaction detected.")
            parent.trackingMode = .none
            withAnimation {
                parent.isInteracting = true
            }
        }

        /// The map view calls this method at the end of a change to the map’s visible region.
        func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
            guard regionDidChangeFromUserInteraction(mapView, gestureState: .ended) else {
                print("mapView:regionDidChangeAnimated - No Interaction detected.")
                return
            }
            print("mapView:regionDidChangeAnimated - User Interaction detected.")
            DispatchQueue.main.async {
                self.parent.trackingMode = .none
                withAnimation { self.parent.isInteracting = false }
            }
        }

        init(_ parent: MapView) {
            self.parent = parent
        }
    }
Delamination answered 26/6, 2023 at 14:2 Comment(0)
C
1

I was trying to have an annotation in the center of the map that is always at the center of the map no matter what the uses does. I tried several of the approaches mentioned above, and none of them were good enough. I eventually found a very simple way of solving this, borrowing from the Anna's answer and combining with Eneko's answer. It basically treats the regionWillChangeAnimated as the start of a drag, and regionDidChangeAnimated as the end of one, and uses a timer to update the pin in real-time:

var mapRegionTimer: Timer?
public func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
    mapRegionTimer?.invalidate()
    mapRegionTimer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true, block: { (t) in
        self.myAnnotation.coordinate = CLLocationCoordinate2DMake(mapView.centerCoordinate.latitude, mapView.centerCoordinate.longitude);
        self.myAnnotation.title = "Current location"
        self.mapView.addAnnotation(self.myAnnotation)
    })
}
public func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
    mapRegionTimer?.invalidate()
}
Chicle answered 25/10, 2017 at 12:40 Comment(0)
B
1

Updated 2023 version of the accepted answer, except it checks all mapView subviews and not just the first subview (to prevent future complications with OS updates). It also doesn't check for the .began state of the gesture, which I found unneeded for my use-case, so feel free to add it within the .contains(where:) block if your use-case requires.

/// Obtains all gestures within the mapView subviews to see if any 
/// of the gestures changed state to began or ended.
/// - Returns: True if any gesture within the mapView changed state to ended, false otherwise.
private var regionDidChangeFromUserInteraction: Bool {
    self.map.subviews // Look at all mapView subviews
        .compactMap { $0.gestureRecognizers } // look at all subview gesture recognizers
        .reduce([], +) // Reduces an Array of Arrays of gestures to an Array of gestures
        .contains(where: { $0.state == .ended }) // if ended returns true else false
}

/// The framework calls this method at the beginning of a change to the map’s visible region.
func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
    guard regionDidChangeFromUserInteraction else {
        print("mapView:regionWillChangeAnimated - No Interaction detected.")
        return
    }
    print("mapView:regionWillChangeAnimated - User Interaction detected.")
}

/// The map view calls this method at the end of a change to the map’s visible region.
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
    guard regionDidChangeFromUserInteraction else {
        print("mapView:regionDidChangeAnimated - No Interaction detected.")
        return
    }
    print("mapView:regionDidChangeAnimated - User Interaction detected.")
}
Barker answered 30/1, 2023 at 2:16 Comment(0)
H
0

enter code hereI managed to do implement this in easiest way, which handles all interaction with map (tapping/double/N tapping with 1/2/N fingers, pan with 1/2/N fingers, pinch and rotations

  1. Create gesture recognizer and add to map view's container
  2. Set gesture recognizer's delegate to some object implementing UIGestureRecognizerDelegate
  3. Implement gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) method
private func setupGestureRecognizers()
{
    let gestureRecognizer = UITapGestureRecognizer(target: nil, action: nil)
    gestureRecognizer.delegate = self
    self.addGestureRecognizer(gestureRecognizer)
}   

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool
{
    self.delegate?.mapCollectionViewBackgroundTouched(self)
    return false
}
Hux answered 8/11, 2016 at 13:0 Comment(0)
G
-1

First, make sure your current view controller is a delegate of the map. So set your Map View delegate to self and add MKMapViewDelegate to your view controller. Example below.

class Location_Popup_ViewController: UIViewController, MKMapViewDelegate {
   // Your view controller stuff
}

And add this to your map view

var myMapView: MKMapView = MKMapView()
myMapView.delegate = self

Second, add this function which is fired when the map is moved. It will filter out any animations and only fire if interacted with.

func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
   if !animated {
       // User must have dragged this, filters out all animations
       // PUT YOUR CODE HERE
   }
}
Gentlefolk answered 13/1, 2019 at 0:42 Comment(0)
N
-1

this worked for me with swift 5

let manager = CLLocationManager()
@IBOutlet weak var map: MKMapView!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    
    manager.delegate = self
    manager.requestWhenInUseAuthorization()
    manager.desiredAccuracy = kCLLocationAccuracyBest
    manager.startUpdatingLocation()
    
    map.delegate = self
}

extension ViewController: MKMapViewDelegate {

  func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    
    if mapView.userLocation.isEqual(annotation) {
        return nil;
    }
    
    var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "AnnotationView")
    
    if annotationView == nil {
        annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "AnnotationView")
    }
    
    annotationView?.isDraggable = true
    annotationView?.canShowCallout = true
    
    return annotationView
  }

  func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, didChange newState: MKAnnotationView.DragState, fromOldState oldState: MKAnnotationView.DragState) {
    switch newState {
    case .starting:
        print(".starting")
    case .dragging:
        print(".dragging")
    case .ending:
        print(".ending")
    case .canceling:
        print(".canceling")
    case .none:
        print(".none")
    default: break
    }
  }
}
Nocturne answered 19/10, 2022 at 6:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.