Multiple annotation callouts displaying in MKMapView - iphone

Is it possible to open simultaneously more then one callout?
The code:
- (void)mapViewDidFinishLoadingMap:(MKMapView *)theMapView {
for (id<MKAnnotation> currentAnnotation in theMapView.annotations) {
[theMapView selectAnnotation:currentAnnotation animated:YES];
}
}
opens only one callout.

Note that there is a method on MKMapView (not MKAnnotationView) for selecting an annotation programmatically that works more or less as you would expect:
- (void)selectAnnotation:(id < MKAnnotation >)annotation animated:(BOOL)animated
However, it automatically deselects any currently annotation at the same time so this doesn't solve your problem.
Oddly, there is a property on MKMapView that appears to hold an array of currently selected annotations:
#property(nonatomic, copy) NSArray *selectedAnnotations
But the documentation on this method says:
"Assigning a new array to this property
selects the first annotation in the
array only."
Just thought this might be of interest.

From a strict API perspective, this does not seem possible.
The -(void)setSelected:(BOOL)selected animated:(BOOL)animated selector on MKAnnotationView states : "You should not call this method directly. An MKMapView object calls this method in response to user interactions with the annotation." so the underlying message is that the selection of annotationView instances in under the full responsability of user selection, and as the user can only select one of them at a time, you shouldn't be able to get several of them selected at the same time.
Even if the documentation says that should not call this method directly, did you try to invoke it anyway with setSelected:YES on several MKAnnotationView instances to see what it gives ?
THE CLEAN WAY I WOULD DO IT : (not tested myself however)
don't rely on the selection mechanism of the MKMapView
subclass the MKAnnotationView to implement a custom one
do the customization in such a way that the callout is part of the annotation view so that you can display several of them.
If you do it like this, you can make appear several callout bubble at the same time and get something that would look like :
alt text http://a1.phobos.apple.com/us/r1000/048/Purple/2b/b2/ec/mzl.ttcsrlee.480x480-75.jpg

Since iOS 11, Apple added new annotation view called MKMarkerAnnotationView.
In func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?, when you dequeue the annotation view, make sure you cast it as MKMarkerAnnotationView (e.g. var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKMarkerAnnotationView), and set view's attributes titleVisibility and subtitleVisibility to .visible.

Related

A MKMapView delegate calling issue

I am facing an issue about MKMapView delegate.
In iOS5, When I clicked a Pin on the mapview,
thedidSelectAnnotationView: delegate will be called first,
and the next is viewForAnnotation: delegate called.
In iOS6, When I clicked a Pin on the mapview,
the viewForAnnotation: will be called first, and the next is didSelectAnnotationView delegate called.
So my app works fine in iOS5, but works bad in iOS6,
it's because that there are coordinate informations that I need setting in the didSelectAnnotationView: delegate,
If viewForAnnotation: delegate are called before the didSelectAnnotationView:, then I'll get the wrong coordinate information.
Anybody got some idea? thank you!
viewForAnnotation can and will be called when ever iOS needs to display one of your annotations. It is not related to when didSelectAnnotationView is called. You may think you found a pattern in iOS 5 but that was just a fluke of something in your app and should never have been relied on. If you use it correctly it will work in iOS 5 and 6 as well as 6.1, 6.2, 6.anything and I'd guess they won't change it much to iOS 7 either. If you look in the signature of viewForAnnotation you'll see that one of the parameters is an annotation. That is the item that your app is trying to draw and it has what ever information you gave the annotation when you called [mapView addAnnotation:myAnnotation]. So cast it to your MKAnnotation implementation and extract the info.
modify the logic.
Prepare the view in viewForAnnotation (which in theory -- can be called at any time anyway). It is the right place for this!
"The annotation view to display for the specified annotation or nil if you want to display a standard annotation view."

Send data from chosen Annotation (InfoBoule button)

I have a mapView which loads annotations with the help of a web service. I parse the data in json in an array and get the values of each annotation.
But now, I want to send the information of the annotation in selection.
As I can think, It mar rather be like the section in UITableView called DidSelectRow...
How I can do this?
If you mean when the user taps one of the annotations in mapView, you have a delegate method for that. From MKMapViewDelegate Protocol Reference
mapView:didSelectAnnotationView:
Set your view controller as delegate for your mapView and then just use this delegate method to be notified when the user taps on one of your annotations.
Link to Apple Documentation on MKMapViewDelegate Protocol

Show callout when tapping overlay

I have an MKMapView with several overlays. Works all just fine, and it's incredible how simple it works. There is, however, one thing I can't get to work. The idea is simple: when a user taps within the area that is covered by an overlay, a callout with some information about that overlay has to come up. The overlays are all MKPolygons, which follow the MKOverlay protocol and therefore the MKAnnotation protocol.
The MKOverlay protocol conforms to the
MKAnnotation protocol. As a result,
all overlay objects are also
annotation objects and can be
treated as one or both in your code.
If you opt to treat an overlay object
as both, you are responsible for
managing that object in two places. If
you want to display both an overlay
view and annotation view for it, you
must implement both the
mapView:viewForOverlay: and
mapView:viewForAnnotation: methods in
your application delegate. It also
means that you must add and remove the
object from both the overlays and
annotations arrays of your map.
This comes from the Apple docs. I tried something like this:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
MKAnnotationView *aView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:nil];
aView.canShowCallout = YES;
}
But that doesn't seem to work. I've tried using gesture recognizers, but I have no idea how to show a callout other than by using the canShowCallOut property...
I suppose you have to add the MKOverlays as annotations also
[self.mapView addAnnotations:myOverlays];
Then return a MKAnnotationView in (mapView:viewForAnnotation) that's not hidden, either a graphic (tap-able) or zero alpha view. Next, add a UITapGestureRecognizer for each MKOverlayView, make sure it works with the map's gestures (UIGestureRecognizerDelegate implementation for simultaneous recognition). Finally when your gesture recognizer fires do this
[self.mapView setSelectedAnnotations:[NSArray arrayWithObject:myOverlayView.overlay]];
I'm not certain that this actually triggers the callOut showing though.
Also make sure your return title and/or subtitle from your overlay object.

How to tell which MKPinAnnotation has been pressed?

i have an MKMapView and have a whole bunch of MKPinAnnotations being shown and all of them have call out feature which shows a more detail view depending on were the location is..
How can I implement a method that tells which pin has been pressed out of the group so it shows a more detail view about that location?
implement the MKMapView delegate:
- (void) mapView: (MKMapView *) mapView didSelectAnnotationView: (MKAnnotationView *) view
and you can do whatever you need in there.
But i think you are really after enabling the map callout accessory. See MapCallouts sample application http://developer.apple.com/library/ios/#samplecode/MapCallouts/Introduction/Intro.html#//apple_ref/doc/uid/DTS40009746

multiple regionDidChangeAnimated calls - what gives?

I have a MKMapView inside a UITableView as a custom cell (don't ask ;) - don't know if it matters really), for which I register a regionDidChangeAnimated delegate method. This method gets called three times when the UITableView is loaded - once with the actual region and then two more times with a region that is way off. In the simulator, I consistently get a region with center (+37.43997405, -97.03125000). On the device, it seems to depend on the location reported by the location manager, which initializes the map view.
Why am I getting three regionDidChangeAnimated calls? And why are the center coordinates for the last two of them off?
This is the code I use to get the center coordinates:
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
CLLocation *l = [[CLLocation alloc] initWithLatitude:self.mapView.centerCoordinate.latitude longitude:self.mapView.centerCoordinate.longitude];
(....)
I have set up a map view inside a custom table view cell and added that cell to a table view (although it definitely should not matter where/how the map view is displayed).
I do not see any unexpected calls to the regionDidChangeAnimated: delegate method.
I see calls to this method only when:
The user changes the position/zoom of the map, OR
Some code changes the center/span of the map
Are you sure that you are seeing unexpected calls? You are not using code to setup the region (center/span) of the map?