Search code examples
swiftuikitmapkit

My map doesn't show annotations from my JSON file (UIKit / Swift /MapKit)


I'm a French Newbie in Swift and I want to make a Map with annotations from a JSON file using UIKit and MapKit. I use UIKit because I would like to use a lot of annotations and I want that the annotations collapse into a cluster Annotation if the user zoom out.

So, the project Built, but none of my annotations are displayed

Thanks a lot for anyone who correct my code. If you have questions, do not hesitate to ask me. Thanks you in advance.

So here my ViewController :

'''

 import CoreLocation
 import UIKit
 import MapKit

class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {


var locations = [Location]()

@IBOutlet weak var mapView: MKMapView!

let manager = CLLocationManager()



override func viewDidLoad() {
    
    super.viewDidLoad()
    mapView.delegate = self



    
    mapView.register(LocationDataMapClusterView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultClusterAnnotationViewReuseIdentifier)

    
}
func AnnotationView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    switch annotation {
    case is MKClusterAnnotation:
        return mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultClusterAnnotationViewReuseIdentifier, for: annotation)
    default:
        return nil
    }
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    manager.desiredAccuracy = kCLLocationAccuracyBest
    manager.delegate = self
    manager.requestWhenInUseAuthorization()
    manager.startUpdatingLocation()
    mapView.showsUserLocation = true
    readFile()
    mapView.addAnnotations(locations)

}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    if let location = locations.first {
        manager.stopUpdatingLocation()
        
        render(location)
    }
}

func render(_ location:CLLocation){
    let coordinate = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
    
    let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
    
    let region = MKCoordinateRegion(center: coordinate,
                                    span: span)
    
    mapView.setRegion(region, animated: true)
}

public func readFile() {
    if let url = Bundle.main.url(forResource : "capital", withExtension: "json"),
       let data = try? Data(contentsOf: url) {
        let decoder = JSONDecoder()
        if let jsonData = try? decoder.decode(JsonData.self, from: data){
            self.locations = jsonData.locations
            print(locations)
        }
    }
}



}

'''

My JSONFile :

'''

{
"locations": [
    {
      "id": 0,
      "name": "New York City",
      "latitude": 40.71,
      "longitude": -74
    },
    {
      "id": 1,
      "name": "Barcelona",
      "latitude": 41.38,
      "longitude": 2.17
    },
    {
      "id": 2,
      "name": "Tokyo",
      "latitude": 35.68,
      "longitude": 139.76
    },
    {
      "id": 3,
      "name": "Atlanta",
      "latitude": 33.74,
      "longitude": -84.38
    },
    {
      "id": 4,
      "name": "Paris",
      "latitude": 48.85,
      "longitude": 2.35
    },
    {
      "id": 5,
      "name": "Hong Kong",
      "latitude": 22.31,
      "longitude": 114.16
    }
  ]
}

'''

and my location class :

'''

 import MapKit
 import UIKit

  class Location: NSObject, Decodable, Identifiable, MKAnnotation {


var id: Int
var name: String
var latitude: Double
var longitude : Double
var coordinate: CLLocationCoordinate2D {
    .init(latitude: latitude, longitude: longitude)
    
}




init(id : Int, name : String, latitude : Double, longitude : Double){
    
    self.id = id
    self.name = name
    self.longitude = longitude
    self.latitude = latitude
}

}




   struct JsonData : Decodable {
       let locations : [Location]
    }

'''


Solution

  • After some research I found my issue :

    1. : mapView.addAnnotations needs to use jsonData.locations and not locations

    '''

    mapView.addAnnotations(jsonData.locations)  
    

    '''

    1. mapView.addAnnotations must be included in the readfile function like that :

    '''

    public func readFile() {
        if let url = Bundle.main.url(forResource : "capital", withExtension: "json"),
           let data = try? Data(contentsOf: url) {
            let decoder = JSONDecoder()
            if let jsonData = try? decoder.decode(JsonData.self, from: data){
                self.locations = jsonData.locations
                mapView.addAnnotations(jsonData.locations)
            }
        }
    }
    

    '''

    1. and at the end I just have to call my function in the viewDidAppear :

    '''

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        manager.desiredAccuracy = kCLLocationAccuracyBest
        manager.delegate = self
        manager.requestWhenInUseAuthorization()
        manager.startUpdatingLocation()
        mapView.showsUserLocation = true
        readFile()
        
    } 
    

    '''