Search code examples
iosswiftmapkitcore-locationmapkitannotation

Automatically adjust zoom to accommodate all markers in iOS in Swift 4


I have a Dictionary of name, lon, and lat.

Raw Data

var places = [["name": "Angkor Wat", "lon": "103.8670", "lat": "13.4125"], ["name": "Pick up zone", "lon": "103.85771740610468", "lat": "13.41250067905404"], ["name": "66-35 Otto Rd", "lon": "-73.8889131530723", "lat": "40.706725952864886"], ["name": "40 Williams St", "lon": "-71.30756271909428", "lat": "42.64240728775266"], ["name": "324 Broadway Rd", "lon": "-71.29124543680823", "lat": "42.68061286243683"], ["name": "39 Kendall Pond Rd", "lon": "-71.33234704167283", "lat": "42.867489706954636"], ["name": "269 Treble Cove Rd", "lon": "-71.30049088921143", "lat": "42.55656906569715"]]

List

enter image description here

Code

This the code I have now.

import UIKit
import MapKit
import CoreLocation

class ViewAllPinsController: UIViewController, MKMapViewDelegate {

    @IBOutlet weak var map: MKMapView!

    var places = [ Dictionary<String,String>()]

    override func viewDidLoad() {
        super.viewDidLoad()

        print(places) // it print fine

        if places.count > 0 {

            for i in 0..<places.count {
                if let name = places[i]["name"] {
                    if let lat = places[i]["lat"] {
                        if let lon =  places[i]["lon"] {
                            if let latitude = Double(lat) {
                                if let longitude = Double(lon) {

                                    //Debug
                                    //print(i)
                                    //print(name)
                                    //print(latitude)
                                    //print(longitude)


                                    let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
                                    let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
                                    let region = MKCoordinateRegion(center: coordinate, span: span)

                                    self.map.setRegion(region, animated: true)

                                    let annotation = MKPointAnnotation()
                                    annotation.coordinate = coordinate
                                    annotation.title = name
                                    self.map.addAnnotation(annotation)



                                }
                            }
                        }
                    }
                }
            }
        }
    }

}

Result

enter image description here


Goal

I want them to be auto-fit all the markers within a screen.

I don't see much guidance on Swift4 after reading posts after posts. How would one go about doing something like this?


Solution

  • You can try

    self.map.showAnnotations(self.map.annotations, animated: true)
    

    Or if you want to customize the region's span

    func zoomToFitMapAnnotations(map:MKMapView)
    {
        if(map.annotations.count == 0)
        {
              return
        }
    
        var topLeftCoord = CLLocationCoordinate2D(latitude: -90, longitude: 180) 
    
        var bottomRightCoord = CLLocationCoordinate2D(latitude: 90, longitude: -180)
    
    
        map.annotations.forEach { 
    
            topLeftCoord.longitude = fmin(topLeftCoord.longitude, $0.coordinate.longitude);
            topLeftCoord.latitude = fmax(topLeftCoord.latitude, $0.coordinate.latitude);
    
            bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, $0.coordinate.longitude);
            bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, $0.coordinate.latitude);
        } 
    
        let resd = CLLocationCoordinate2D(latitude: topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5, longitude: topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5)
    
        let span = MKCoordinateSpan(latitudeDelta: fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.3, longitudeDelta: fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.3)
    
        var region = MKCoordinateRegion(center: resd, span: span);
    
        region = map.regionThatFits(region)
    
        map.setRegion(region, animated: true)
    
    
    }