简体   繁体   中英

Swift MapView not adding annotation to Map

So for my mapView, I am receiving coordinates from another VC by passing it longitude and latitude through a global array like such:

Adding the latitude and longitude into the array:

var location_one: [String: Any] = ["title": eventName, "latitude": latitude, "longitude": longitude]
    locations.append(location_one)
    if let tbc = self.tabBarReference {
        if let map = tbc.viewControllers?[1] as? MapVC {
            map.loadViewIfNeeded()
            map.add(newLocation:location_one)
        }
     }

Receiving the coordinates on the MapViewVC:

    func add(newLocation location_one:[String:Any]) {
        let momentaryLat = (location_one["latitude"] as! NSString).doubleValue
        let momentaryLong = (location_one["longitude"] as! NSString).doubleValue
        let annotation = MKPointAnnotation()
        annotation.title = location_one["title"] as? String
        annotation.coordinate = CLLocationCoordinate2D(latitude: momentaryLat as CLLocationDegrees, longitude: momentaryLong as CLLocationDegrees)
        map.addAnnotation(annotation)

        //        self.map.centerCoordinate = annotation.coordinate
    }

viewForannotation code:

func mapView(_ map: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {



    let identifier = "pinAnnotation"
    var annotationView = map.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView

    if annotationView == nil {
        annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
        annotationView?.canShowCallout = true
    }

    annotationView?.annotation = annotation
    return annotationView
}

The coordinates are properly transferring and the func add is being called upon (verified using a break statement), however when I go to the MapView in the simulator, the annotation isn't being placed. I have no idea what is going on, as this worked properly in another App I tested, but don't have a clue what could cause it to mess up.

I also have code that finds the user's current location and places a pin based on that... perhaps that could mess up the add coordinate code?

I'd suggest double checking the numeric values of momentaryLat and momentaryLong , because it's possible that due to parsing problems, they're not what you think they are (eg make sure they're not 0.0, in the Atlantic Ocean!). We'd have to see what location_one["latitude"] values were before you converted it to NSString and extracted the double value from that. Break it down into separate steps, and the problem will likely jump out at you.


Your viewFor looks fine. Unrelated, I'd suggest putting the annotationView?.annotation = annotation inside the else clause of the preceding if statement (no need to set the annotation if you just created the MKPinAnnotationView using that same annotation ... you only need to do this if reusing the annotation view). And I'd also generally check to make sure the annotation is not the MKUserLocation because we generally let the map view render that for us.

func mapView(_ map: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    if annotation is MKUserLocation { return nil }   // let the OS show user locations itself

    let identifier = "pinAnnotation"
    var annotationView = map.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView

    if annotationView == nil {
        annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
        annotationView?.canShowCallout = true
    } else {
        annotationView?.annotation = annotation
    }

    return annotationView
}

But neither of those two observations have anything to do with your issue of the missing annotation.


Remember, the viewForAnnotation (or viewFor in Swift 3) method is only called when one or more of the map's annotations has a coordinate that falls within the visible portion of the map and it therefore concludes that it needs to render the associated annotation views. So, one would not expect it to be called until (a) the map tries to draw itself and (b) one or more of the annotations have coordinates within (or near) the visible portion of the map.

For example, if you have 100 annotations added to the map object, of which only 10 fall within the visible portion of the map, only 10 annotation views will be created. And if you scroll the map such that 5 fall out of view and 7 more scroll into view, it call viewForAnnotation 7 more times, once for each newly visible annotation. The viewForAnnotation will likely successfully dequeue/reuse the 5 annotation views that scrolled out of view and and will only create new annotation views for the two additional ones. (It's more complicated than that, but that's the basic idea.)

It's analogous to table/collection views, where cells are created only for the visible cells. So, if you have 100 objects in your model, but only 12 rows are visible in a table, you'll create 12 cells only. And as a row scrolls out of view, it becomes available for dequeue/reuse for future rows that scroll into view. It's a common pattern that you'll see throughout iOS, where computationally-expensive view objects are only created as needed, and reused wherever possible.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM