skip to Main Content

How can I calculate the max zoom out in MapKit to show the entire globe?

Example:

let region: MKCoordinateRegion = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: -37.8136, longitude: 144.9631), span: MKCoordinateSpan(latitudeDelta: 170, longitudeDelta: 170))

If instead of 170 I put 200 the App crash telling me:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid Region <center:-37.81360000, +144.96310000 span:+200.00000000, +200.00000000>'

2

Answers


  1. The Earth has 2 hemispheres, divided into 90 degrees each. So latitude range is from -90 to 90 i.e. latitudeDelta cannot be more than 180 degrees.

    Longitude range is from -180 to 180, so longitudeDelta max is 360 degrees.

    To show a globe, set MapView.mapType = .hybridFlyover or MapView.mapType = .satelliteFlyover.

    Login or Signup to reply.
  2. When initializing MKCoordinateRegion with coordinate and span and use MKMapView.setRegion(_ region: MKCoordinateRegion, animated: Bool)

    Changing just the center coordinate of the region can still cause the span values to change implicitly. The span values might change because the distances represented by a span change at different latitudes and longitudes and the map view may need to adjust the span to account for the new location

    Ref: MKMapView.setRegion(_ region: MKCoordinateRegion, animated: Bool)

    Here is my workaround with MKMapCamera.

    Code in MapScreen.swift

    
    import UIKit
    import MapKit
    import CoreLocation
    
    class MapScreen: UIViewController {
    
        @IBOutlet weak var mapView: MKMapView!
        
        override func viewDidLoad() {
            super.viewDidLoad()
    
            self.mapView.mapType = .hybridFlyover // Change to satellite mode
            // Or you can use .satelliteFlyover
        
            // We delay update by 1 second to get final size of mapView on UI.
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
                self.focusOnPointAndShowGlobe()
            }
        }
        
        func focusOnPointAndShowGlobe() {
            let mapHeight = mapView.bounds.height // the constraint of visible Map area will base on HEIGHT of mapview
    
            // These are standard/base value from adjustment
            let standardMapHeight: CGFloat = 450
            let standardCameraDistance: CGFloat = 24 * 1000 * 1000 // 24,000 km
            
            let targetDistance = (mapHeight / standardMapHeight) * standardCameraDistance
            let center = CLLocationCoordinate2D(latitude: -37.8136, longitude: 144.9631)
            let camera = MKMapCamera(lookingAtCenter: center, fromDistance: targetDistance, pitch: 0, heading: 0)
            self.mapView.setCamera(camera, animated: true)
        }
    }
    

    MapView layout in Xib (I’m using fullscreen layout)

    enter image description here

    This is result on Portrait mode, focusOnPointAndShowGlobe() will focus on center location then move away from the Earth to disply entire globe, when you open this screen or call focusOnPointAndShowGlobe() again.

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search