开发者

Issue with overlapping annotations (MKAnnotationView) on map

In my iphone application, I'm using MapKit with MKMapView and custom MKAnnotationView.

The problem is when annotations overlap on map (in my app, annotations are photos and those photos may overlap) and when you tap on the annotation that appears on front, it's another annotation (on back) which receives the event (seems to be random).

I didn't find any way to send the event to the front annotation. I cannot believe this bug/problem doesn't have any solution!

Z ordering and Order of overlapping annotations questions on stackoverflow did not help me that much.

Please any idea is welcome (even dirty solutions)!

Here's some of my code (nothing fancy, very common):

CustomAnnotation.h

@interface CustomAnnotation : NSObject <MKAnnotation> {
   @private
   CustomAnnotationVi开发者_JAVA技巧ew* view;
}

    @property (nonatomic, retain) CustomAnnotationView* view;

@end

CustomAnnotation.m

@implementation CustomAnnotation

@synthetize view;

CustomAnnotationView.h

@interface CustomAnnotationView : MKAnnotationView {
}

@end

CustomAnnotationView.m

@implementation CustomAnnotationView

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
// Do something related to the annotation tapped
}

@end

Main class ... // Annotations are added and some of them overlaps with others.

- (void)addAnnotation:(CustomAnnotation*)annotation {
    [map addAnnotation:annotation];
}

...

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {

    NSString* identifier = getIdentifierFromAnnotation(annotation);
    CustomAnnotationView* view;
    if(!(view = (CustomAnnotationView*)[map dequeueReusableAnnotationViewWithIdentifier:identifier])) {
        view = [[CustomAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier: identifier];
        [(CustomAnnotation*)annotation setView:view];
        [view release];
    }
    return view;
}


Finally, the best way I found and that avoids loosing map funcionalities is to:

  • let the touch listener on CustomAnnotationView (touchesEnded) (on each annotation)

  • when receiving touch event, transfer the event to main class

  • main class loops on annotations and keeps the annotation that has a good location (touch event in the annotation frame) and that is in front

It works pretty well.


See the solution to this question. Basically you'll create a transparent UIView which will intercept all of the touches. I haven't tried it, but this may be more trouble than it's worth if you have to reimplement all of the pinch-to-zoom functionality in MKMapView.

If you have two (or more) MKAnnotations co-located you can repeatedly tap to toggle between the two. That should work without any changes to your app.


Following up on Alexandre's answer, I disabled all my custom MKAnnotationViews objects with

annView.enabled = NO

so they don't respond to the MKMapView default select behavior, and implemented in my custom MKAnnotationView the following:

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
 self.enabled = YES;
 [(MKMapView*)self.superview selectAnnotation:self.annotation animated:NO];
}

This solution works great on iOS 4. It seems like disabling an MKAnnotationView doesn't disable its userInteractionEnabled, whereas on iOS 3 it does. Still looking for a solution for iOS 3...

EDIT: actually, this seems to be a bug in iOS 4.1. In iOS 4.2, disabling a pin also disables the touch events. Therefore this method only works for 4.1 and possibly 4.0.


I've added the UITapGestureRecognizer to the view at the front and that solved the issue for me.

In your case, adding a gesture recognizer to CustomAnnotationView should solve the issue.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜