1

I just want to return the name of the country where the black circle stops. [1]: https://i.stack.imgur.com/Re5FK.jpg Example in the picture above

I know it can be done by CLGeocoder and CLPlacemark along with Mapkit, and I have tried a lot but always got an error and the app would crash.

my code

import MapKit
import SwiftUI

struct MapView: UIViewRepresentable {
    
    @Binding var centralCoordinate: CLLocationCoordinate2D
    var anotations: [MKPointAnnotation]
    
    func makeUIView(context: Context) -> MKMapView{
        let mapview = MKMapView()
        mapview.delegate = context.coordinator
        return mapview
    }
    
    func updateUIView(_ view: MKMapView, context: Context) {
        
        if anotations.count != view.annotations.count {
            view.removeAnnotations(view.annotations)
            view.addAnnotations(anotations)
        }
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, MKMapViewDelegate {
        var parent: MapView
        
        init(_ parent: MapView) {
            self.parent = parent
        }
        
        func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {

            parent.centralCoordinate = mapView.centerCoordinate

            let geoCoder = CLGeocoder()
            let location = CLLocation(latitude: mapView.centerCoordinate.latitude, longitude: mapView.centerCoordinate.longitude)
            geoCoder.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in
                
                // Place details
                var placeMark: CLPlacemark!
                placeMark = placemarks?[1]
                // Country
                if let country = placeMark.country {
                    print(country)
                }
            })
        }
    }
}

extension MKPointAnnotation{
    static var eample: MKPointAnnotation {
        let annotaton = MKPointAnnotation()
        annotaton.title = "London"
        annotaton.subtitle = "Home TO 2012 Summer Olampics"
        annotaton.coordinate = CLLocationCoordinate2D(latitude: 51.5, longitude: -0.13)
        return annotaton
    }
}

struct MapView_Previews: PreviewProvider {
    static var previews: some View {
        MapView(centralCoordinate: .constant(MKPointAnnotation.eample.coordinate), anotations: [MKPointAnnotation.eample])
    }
}

my view code

import  MapKit
import SwiftUI

struct MapViewIntegration: View {
    
    @State private var centercoordinate = CLLocationCoordinate2D()
    @State private var locations = [MKPointAnnotation]()
    
    var body: some View {
        ZStack {
            MapView(centralCoordinate: $centercoordinate,anotations: locations)
        .edgesIgnoringSafeArea(.all)
        Circle()
        .opacity(0.3)
        .frame(width: 32, height: 32)
            VStack{
                Spacer()
                HStack{
                    Spacer()
                    Button(action: {
                        let newLocations = MKPointAnnotation()
                           newLocations.coordinate = self.centercoordinate
                           self.locations.append(newLocations)
                    }) {
                        Image(systemName: "plus")
                    }.padding()
                    .background(Color.white)
                    .font(.title)
                    .clipShape(Circle())
                    .padding(.trailing)
                }
            }
        }
    }
}

struct MapViewIntegration_Previews: PreviewProvider {
    static var previews: some View {
        MapViewIntegration()
    }
}

please help, thanks in advance

  • Where does your code crash and what error message to you get? – Magnas Aug 15 '20 at 14:01
  • it crashes on this line of code ``` if let country = placeMark.country { print(country) } ``` saying "Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value" – fouzan ahmed Aug 15 '20 at 16:56
  • Try printing each of those values (placeMark, placeMark.country, country) immediately before that line to see which one prints nil. That may narrow the issue down. – Sanzio Angeli Aug 20 '20 at 15:33
  • @SanzioAngeli placeMark returns nil so print(placeMark.country) causes a crash – fouzan ahmed Aug 22 '20 at 07:42
  • try placemark[0] instead of placemark[1] - Indexing in swift starts at 0 – Sanzio Angeli Aug 22 '20 at 21:50
  • @SanzioAngeli I tried as you said but it still returns nil – fouzan ahmed Aug 23 '20 at 07:11
  • 1
    @SanzioAngeli thanks for your advice the problem was when I moved the map it would send sooo many requests to the apple server that the request would fail and throw an error thank u sooo much for your answer – fouzan ahmed Sep 16 '20 at 05:48
  • You should answer the question yourself and then mark as correct so others can see the work you did to find the solution – Sanzio Angeli Sep 16 '20 at 22:12
  • @thanks for your help thanks a lot. Can you plz help me with this question https://stackoverflow.com/q/63902637/13748710 or if you don’t know the answer can you plz share it your friend’s. – fouzan ahmed Sep 17 '20 at 04:47

1 Answers1

0

this answer was given by @SanzioAngeli

Replace this code with

   func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {

            parent.centralCoordinate = mapView.centerCoordinate

            let geoCoder = CLGeocoder()
            let location = CLLocation(latitude: mapView.centerCoordinate.latitude, longitude: mapView.centerCoordinate.longitude)
            geoCoder.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in
                
                // Place details
                var placeMark: CLPlacemark!
                placeMark = placemarks?[1]
                // Country
                if let country = placeMark.country {
                    print(country)
                }
            })
        }
    }

this

   func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {

            parent.centralCoordinate = mapView.centerCoordinate

            let geoCoder = CLGeocoder()
            let location = CLLocation(latitude: mapView.centerCoordinate.latitude, longitude: mapView.centerCoordinate.longitude)
            geoCoder.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in
                
                // Place details
                var placeMark: CLPlacemark!
                placeMark = placemarks?[0]
                // Country
                if let country = placeMark.country {
                    print(country)
                }
            })
        }
    }

@SanzioAngeli thanks.

Remember not to send too many requests at a time all the requests will fail and throw a fatal error.