Determine If Mkmapview Was Dragged/Moved in Swift 2.0

determine if MKMapView was dragged/moved

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.

Stop Updating Location when I drag the mapview

Selector syntax has changed in Swift 3. Your gesture recognizer should now look like this:

let mapDragRecognizer = UIPanGestureRecognizer(target: self, action: #selector(didDragMap))

func didDragMap(_ gestureRecognizer: UIGestureRecognizer) {
if (gestureRecognizer.state == UIGestureRecognizerState.began) {
print("Map drag began")
self.locationManager.stopUpdatingLocation()
}
if (gestureRecognizer.state == UIGestureRecognizerState.ended) {
print("Map drag ended")
}
}

Note that didDragMap(_:) is declared according to the new Swift API Design Guidelines

I would also replace your if statements with a switch statement as the compiler is able to optimize it better once there are more than two cases, and it is more clear. i.e.

func didDragMap(_ gestureRecognizer: UIGestureRecognizer) {
switch gestureRecognizer.state {
case .began:
print("Map drag began")
self.locationManager.stopUpdatingLocation()

case .ended:
print("Map drag ended")

default:
break
}
}

Detecting when a user scrolls MKMapView a certain distance?

I personally find it more helpful when someone can post a snippet of code versus general prose about how one might go about this. Here's what I came up with- roughly hacked out to simply better answer this question:

In a header file I have:

#define SCROLL_UPDATE_DISTANCE          80.00

and in my view (that is both a delegate for CLLocationManagerDelegate, MKMapViewDelegate):

// this method is called when the map region changes as a delegate of MKMapViewDelegate
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
NSLog(@"regionDidChangeAnimated");
MKCoordinateRegion mapRegion;
// set the center of the map region to the now updated map view center
mapRegion.center = mapView.centerCoordinate;

mapRegion.span.latitudeDelta = 0.3; // you likely don't need these... just kinda hacked this out
mapRegion.span.longitudeDelta = 0.3;

// get the lat & lng of the map region
double lat = mapRegion.center.latitude;
double lng = mapRegion.center.longitude;

// note: I have a variable I have saved called lastLocationCoordinate. It is of type
// CLLocationCoordinate2D and I initially set it in the didUpdateUserLocation
// delegate method. I also update it again when this function is called
// so I always have the last mapRegion center point to compare the present one with
CLLocation *before = [[CLLocation alloc] initWithLatitude:lastLocationCoordinate.latitude longitude:lastLocationCoordinate.longitude];
CLLocation *now = [[CLLocation alloc] initWithLatitude:lat longitude:lng];

CLLocationDistance distance = ([before distanceFromLocation:now]) * 0.000621371192;
[before release];
[now release];

NSLog(@"Scrolled distance: %@", [NSString stringWithFormat:@"%.02f", distance]);

if( distance > SCROLL_UPDATE_DISTANCE )
{
// do something awesome
}

// resave the last location center for the next map move event
lastLocationCoordinate.latitude = mapRegion.center.latitude;
lastLocationCoordinate.longitude = mapRegion.center.longitude;

}

Hope that sends you in the right direction.

distanceFromLocation is iOS 3.2 and later.
initWithLatitude is iOS 2.0 and later.
MKCoordinateRegion is iOS 3.0 and later.
MKMapView centerCoordinate is iOS 3.0 and later.

Also- please feel free to jump in and set me straight where I've erred. I'm figuring all of this out myself- but this is working fairly well for me so far.

Hope this helps someone.

iPad and MapKit -Can't Get Draggable Marker to Drag

You need to set your anootation View to be draggable.

[ret setDraggable:YES]

MKMapView in a UITableViewCell

UITableView scrolling speed is contingent upon how fast you can turn your data into pixels. Sweet macintosh do you have a lot of drawing code!!

What can you do?

You can do all sorts of things to make your cells render faster: Draw the cells using CoreGraphics, cache them aggressively, or simplify them. As a rule of thumb, avoid complex UI element hierarchies.

Creating a NSDateFormatter can take up to a half of a second. Create one once, then hold a reference to it, or use a shared 'factory' for storing and creating NSDateFormatter instances.

There is also the chance that MKMapView's scrolling competes with your UITableView's scrolling. Disable scrolling on the MKMapView.

I would be amiss if I didn't tell you that the blocks you use may hold a reference to old cells to maintain a certain context/scope. This extra (potentially strong) reference keeps the cells in memory for a few seconds.

Oh shoot, none of this works!

Try using CoreGraphics to get a UIImage from an offscreen MKMapView. Make sure you're not instantiating a new one each time, as that's probably expensive.

// Untested

UIGraphicsBeginImageContextWithOptions(_mapView.frame.size, YES, 0);
CGContextRef context = UIGraphicsGetCurrentContext();

CGAffineTransform flipVertical = CGAffineTransformMake( 1, 0, 0, -1, 0, _mapView.frame.size.height);
CGContextConcatCTM(context, flipVertical);

[_mapView.layer renderInContext:context];

UIImage *renderedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Do stuff with renderedImage

This image could be cached in indefinitely, maps don't change too often.

If you really want to get fancy, you could make a shared instance that holds this MKMapView and renders parts of a map. You could probably hook into the map tile rendering in MKMapView instead of using the code above.

UPDATE: (6.24.14)

In iOS 7, you can use a specialized class (you don't need to hold onto an MKMapView anymore) to render maps, see this Gist I just wrote:

https://gist.github.com/fhsjaagshs/2e0471b41bb7666efa7d

This method is better because you don't need to hold onto an MKMapView, you don't need to write any potentially slow drawing code (CoreGraphics is CPU-based drawing, MKMapSnapshotter is probably GPU-based), and it's asynchronous! You can drop a UIActivityIndicatorView into your cell, and when the callback loads, kill it and replace it with the UIImage.



Related Topics



Leave a reply



Submit