How do you check if an MKAnnotation is available within a MKCoordinateRegion
Asked Answered
C

2

8

I've noticed that if I use MKMapView's selectAnnotation:animated:, that it will scroll my map off screen if the MKAnnotation is not displayed in the current MKCoordinateRegion that my map is displaying.

Is there a trivial way to check if an annotation is currently on screen within the specified MKCoordinateRegion? I'd like to be able to select an annotation that's only on screen and not something offscreen.

Cassaundracassava answered 30/12, 2011 at 2:55 Comment(0)
D
29

Use the annotationsInMapRect: method in the MKMapView class. It returns a NSSet of all annotation objects that are visible in the given map rect. Use the containsObject: method of NSSet to test if the annotation is present in that set of visible annotations.

MKMapRect visibleMapRect = aMapView.visibleMapRect;
NSSet *visibleAnnotations = [aMapView annotationsInMapRect:visibleMapRect];
BOOL annotationIsVisible = [visibleAnnotations containsObject:someAnnotation];

Also visibleMapRect is same as the region but just a different form of representation. Take from the docs,

visibleMapRect

The area currently displayed by the map view.

@property(nonatomic) MKMapRect visibleMapRect

This property represents the same basic information as the region property but specified as a map rectangle instead of a region.

Dalton answered 30/12, 2011 at 3:4 Comment(3)
Does this account for custom annotationviews that are larger than the standard MKAnnotationView? What I mean is that it may be visible, but it may be somewhat offscreen.Arlinearlington
Does this account for map rotation? Take a look at the image in this article to see how the region is represented in relation to the screen when the map is rotated.Polivy
@JoshBernfeld did you find a solution for map rotation?Chemist
H
0

15-year update...

Syntax update to the excellent @Anurag answer

Number of your annotations which are currently visible:

let k = mapView.annotations(in: mapView.visibleMapRect).count 

Check if a particular annotation is still on screen:

let momAnnotation = mapView.annotations[12]
let momVisible = mapView
    .annotations(in: mapView.visibleMapRect)
    .contains(momPosition)

A very common pattern:

func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
    if mapView.annotations(in: mapView.visibleMapRect).count <
                                         mapView.annotations.count {
        .. show your "reset view" button
    }
    else {
        .. hide your "reset view" button
    }
}

///Widen the map to include all annotations, "default view"
@IBAction func tapResetViewButton() {
    mapView.showAnnotations(mapView.annotations, animated: true)
}

MKMapRect vs. CGRect:

Just as @Anurag says, take care for the difference between MKMapRect and plain-old bounds/frames, they are quite different.

PERFORMANCE ISSUE:

Note that mapView.annotations(in: ..).count is INCREDIBLY faster than counting them yourself. As a general rule, never iterate through mapView.annotations, because, there's likely a built-in function which does what you need incredibly faster.

Henbane answered 17/6 at 12:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.