Reputation: 89
I am trying to limit maximum zoom level in my swift application without which my app is crashing with memory overload during zooming. I am following the suggestions present in Is there way to limit MKMapView maximum zoom level? One of the suggestion is to implement regionDidChangeAnimated with following code in Objective-C. Following is the code
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
// Constrain zoom level to 8.
if( [mapView zoomLevel] < 8 )
{
[mapView setCenterCoordinate:mapView.centerCoordinate
zoomLevel:8
animated:NO];
}
}
I am trying to convert it into Swift and facing problems. How do I convert into swift
Upvotes: 2
Views: 1898
Reputation: 1292
I have a swift version of what you looking for, i can't remember where i got it from but i shouldn't be credited for it.
extension MKMapView {
var MERCATOR_OFFSET : Double {
return 268435456.0
}
var MERCATOR_RADIUS : Double {
return 85445659.44705395
}
private func longitudeToPixelSpaceX(longitude: Double) -> Double {
return round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * Double.pi / 180.0)
}
private func latitudeToPixelSpaceY(latitude: Double) -> Double {
return round(MERCATOR_OFFSET - MERCATOR_RADIUS * log((1 + sin(latitude * Double.pi / 180.0)) / (1 - sin(latitude * Double.pi / 180.0))) / 2.0)
}
private func pixelSpaceXToLongitude(pixelX: Double) -> Double {
return ((round(pixelX) - MERCATOR_OFFSET) / MERCATOR_RADIUS) * 180.0 / Double.pi;
}
private func pixelSpaceYToLatitude(pixelY: Double) -> Double {
return (Double.pi / 2.0 - 2.0 * atan(exp((round(pixelY) - MERCATOR_OFFSET) / MERCATOR_RADIUS))) * 180.0 / Double.pi;
}
private func coordinateSpan(withMapView mapView: MKMapView, centerCoordinate: CLLocationCoordinate2D, zoomLevel: UInt) ->MKCoordinateSpan {
let centerPixelX = longitudeToPixelSpaceX(longitude: centerCoordinate.longitude)
let centerPixelY = latitudeToPixelSpaceY(latitude: centerCoordinate.latitude)
let zoomExponent = Double(20 - zoomLevel)
let zoomScale = pow(2.0, zoomExponent)
let mapSizeInPixels = mapView.bounds.size
let scaledMapWidth = Double(mapSizeInPixels.width) * zoomScale
let scaledMapHeight = Double(mapSizeInPixels.height) * zoomScale
let topLeftPixelX = centerPixelX - (scaledMapWidth / 2);
let topLeftPixelY = centerPixelY - (scaledMapHeight / 2);
//find delta between left and right longitudes
let minLng = pixelSpaceXToLongitude(pixelX: topLeftPixelX)
let maxLng = pixelSpaceXToLongitude(pixelX: topLeftPixelX + scaledMapWidth)
let longitudeDelta = maxLng - minLng;
let minLat = pixelSpaceYToLatitude(pixelY: topLeftPixelY)
let maxLat = pixelSpaceYToLatitude(pixelY: topLeftPixelY + scaledMapHeight)
let latitudeDelta = -1 * (maxLat - minLat);
let span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta)
return span
}
func zoom(toCenterCoordinate centerCoordinate:CLLocationCoordinate2D ,zoomLevel: UInt) {
let zoomLevel = min(zoomLevel, 20)
let span = self.coordinateSpan(withMapView: self, centerCoordinate: centerCoordinate, zoomLevel: zoomLevel)
let region = MKCoordinateRegionMake(centerCoordinate, span)
self.setRegion(region, animated: true)
}
}
Usage example:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = manager.location?.coordinate {
mapView.zoom(toCenterCoordinate: CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude), zoomLevel: 16)
}
}
Upvotes: 1
Reputation: 126
I think you can use mapView.camera.altitude
instead.
So it will be like:
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
if mapView.camera.altitude < 8 {
mapView.camera.altitude = 8
}
}
Also remember that you will have to add MKMapViewDelegate
as a superclass (class ViewController : UIViewController, MKMapViewDelegate
)
Good luck!
Best Regards Eskils.
Upvotes: 1