Failed to set maprect to show all annotations
Asked Answered
F

4

7

I have 2 annotations to display on the mapview, but unable to set the maprect to show all of them on screen without requiring users to zoom out.

I tried with showAnnotations but no luck. Anyone has been able to do this in Swift and Xcode 6.1.1?

Here is my code:

class ViewController: UIViewController, MKMapViewDelegate {


    @IBOutlet var map: MKMapView!

    override func viewDidLoad() {
        super.viewDidLoad()

        var mapView = map
        // 1
        let point1 = CLLocationCoordinate2D(latitude: 38.915565, longitude: -77.093524)
        let point2 = CLLocationCoordinate2D(latitude: 38.890693, longitude: -76.933318)

        //2
        let annotation = MKPointAnnotation()
        annotation.setCoordinate(point1)
        annotation.title = "point1"
        map.addAnnotation(annotation)

        let annotation2 = MKPointAnnotation()
        annotation2.setCoordinate(point2)
        annotation2.title = "point2"
        map.addAnnotation(annotation2)

        //3
        // option1: set maprect to cover all annotations, doesn't work
        var points = [annotation, annotation2]
        var rect = MKMapRectNull
        for p in points {
            let k = MKMapPointForCoordinate(p.coordinate)
            rect = MKMapRectUnion(rect, MKMapRectMake(k.x, k.y, 0.1, 0.1))
            println("result: x = \(rect.origin.x) y = \(rect.origin.y)")
        }

        map.setVisibleMapRect(rect, animated: true)

        // option 2: using showAnnotations, doesn't work
        //map.showAnnotations(points, animated: true)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


     }

This is what I got currently: enter image description here

This is what I expected to see: enter image description here

Thanks for your help.

Fowlkes answered 26/1, 2015 at 16:51 Comment(7)
Can you please explain what you mean exactly by saying showAnnotations "doesn't work"? What happens? For setVisibleMapRect, you might want to apply an inset (see https://mcmap.net/q/1475076/-iphone-mkmapview-set-span-region-value-to-show-all-pins-on-map for an example). Also, you've implemented viewForAnnotation which shows a custom image for the annotations but in the screenshot that you "expect", it shows the default red pins. Why do you expect default red pins?Bichromate
Anna, what I meant for "doesn't work" for showAnnotations is that didn't show all pins like in the expected screen.Fowlkes
The code with showAnnotations looks fine. If you prefer setVisibleMapRect instead, add an inset. Comment out the viewForAnnotation method completely while testing the zoom. Once the zoom is fixed, then fix the problem with viewForAnnotation. If no pins are showing, make sure viewForAnnotation is being called (make sure map delegate is set, make sure image file exists).Bichromate
Anna, if you said "showAnnotations looks fine", why it didn't work? Did you try that code yet?Fowlkes
Yes, I tried the code posted in the question and it worked. The showAnnotations worked without any changes. For the setVisibileMapRect, an inset needs to be applied so the annotations are not exactly at the edge of the screen.Bichromate
Thanks. Is it possible for you to send me your test code? I mean the entire project. There must be something wrong on my side that makes showAnnotations not work.Fowlkes
Let us continue this discussion in chat.Fowlkes
F
21

I finally found out why the pins of the annotations had not been displayed in the visible region of the screen. I think the MapKit framework behaves a bit different than in the previous versions. Since I use autolayout to allow the map to expand to the entire screen for all devices (iPhones, iPad), setVisibleMapRect or mapView.showAnnotations of the map should be invoked in mapViewDidFinishLoadingMap, not in viewDidLoad of the view controller

For example:

 func mapViewDidFinishLoadingMap(_ mapView: MKMapView) {
     // this is where visible maprect should be set
     mapView.showAnnotations(mapView.annotations, animated: true)  
 }
Fowlkes answered 27/1, 2015 at 16:3 Comment(1)
It's better to show annotations inside the mapViewDidFinishRenderingMapdelegate method instead.Rabaul
D
3

I had this same problem when I called

viewDidLoad() {
    mapView.showAnnotations(myAnnotations, animated: false)
}

However, moving the call to viewDidLayoutSubviews() also seems to fix the problem (not that isInitialLoad is initialized to true in viewDidLoad).

viewDidLayoutSubviews() {
    if isInitialLoad {
        mapView.showAnnotations(myAnnotations, animated: false)
        isInitialLoad = false
    }
} 

The difference (I think it is an advantage) of putting the call in viewDidLayoutSubviews is that the map hasn't actually displayed yet, so your initial display is that area defined by the annotations. However, it seems that it is called every time the map zooms, so you need to be sure to only call it the first time.

Decency answered 15/1, 2016 at 4:5 Comment(0)
T
2

For me using showing annotations after map did finish loading did not work.

func mapViewDidFinishLoadingMap(mapView: MKMapView!) {
 // this is where visible maprect should be set
 mapView.showAnnotations(mapView.annotations, animated: true)  
}

Besides showing the annotation, I needed to calculate polylines to connect the annotations and map finished loading was triggered too early.

Instead I tried mapViewDidFinishRenderingMap and it worked perfectly fine. See example below:

//MARK: - Show all objects after adding them on the map
func mapViewDidFinishRenderingMap(mapView: MKMapView, fullyRendered: Bool) {
    mapView.showAnnotations(mapStages, animated: true)
}
Teleology answered 20/9, 2016 at 9:36 Comment(0)
M
2

You can try this. I created an extension to show all the annotations using some code from here and there in swift 2.3. This will not show all annotations if they can't be shown even at maximum zoom level.

import MapKit

extension MKMapView {
    func fitAllAnnotations() {
        var zoomRect = MKMapRectNull;
        for annotation in annotations {
            let annotationPoint = MKMapPointForCoordinate(annotation.coordinate)
            let pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0.1, 0.1);
            zoomRect = MKMapRectUnion(zoomRect, pointRect);
        }
        setVisibleMapRect(zoomRect, edgePadding: UIEdgeInsetsMake(20, 20, 20, 20), animated: true)
    }
}
Mcnamee answered 8/3, 2017 at 7:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.