2014-06-12 8 views
5

Ich habe eine benutzerdefinierte Unterklasse von MKPinAnnotationView, die einen benutzerdefinierten Aufruf anzeigt. Ich möchte Berührungsereignisse innerhalb dieser Anmerkung behandeln.Verhindern, dass MKMapView die Auswahl ändert (sauber)

Ich habe eine funktionierende Lösung (unten), aber es fühlt sich einfach nicht richtig an. Ich habe eine Faustregel, dass, wenn ich performSelector: .. withDelay: benutze, ich das System kämpfe, anstatt mit ihm zu arbeiten.

Hat jemand eine gute, saubere Lösung für die aggressive Ereignisbehandlung von MKMapView und die Verarbeitung von Annotation-Selektionen?

Meine aktuelle Lösung:

(Alle Code aus meiner Anmerkungsauswahl Klasse)

ich meine eigenen Treffertests tun (ohne dass dies meine Geste recognisers als Kartenansicht nicht Feuer verbrauchen die Ereignisse :

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event; { 
    // To enable our gesture recogniser to fire. we have to hit test and return the correct view for events inside the callout. 

    UIView* hitView = nil; 

    if (self.selected) { 
     // check if we tpped inside the custom view 
     if (CGRectContainsPoint(self.customView.frame, point)) 
      hitView = self.customView; 
    } 

    if(hitView) { 
     // If we are performing a gesture recogniser (and hence want to consume the action) 
     // we need to turn off selections for the annotation temporarily 
     // the are re-enabled in the gesture recogniser. 
     self.selectionEnabled = NO; 

     // *1* The re-enable selection a moment later 
     [self performSelector:@selector(enableAnnotationSelection) withObject:nil afterDelay:kAnnotationSelectionDelay]; 

    } else { 
     // We didn't hit test so pass up the chain. 
     hitView = [super hitTest:point withEvent:event]; 
    } 

    return hitView; 
} 

Bitte beachte, dass ich auch Auswahlen auszuschalten, so dass in meinem setSelected außer Kraft gesetzt ich die Abwahl ignorieren

0.

Es ist die Linie kommentierte , die ich nicht mag, aber es ist auch ziemlich haarig am Ende des verzögerten Feuer Theta. Ich muss die Superview-Kette zurücklaufen, um zur mapView zu gelangen, damit ich sie davon überzeugen kann, dass die Auswahl immer noch vorhanden ist.

// Locate the mapview so that we can ensure it has the correct annotation selection state after we have ignored selections. 
- (void)enableAnnotationSelection { 
    // This reenables the seelction state and resets the parent map view's idea of the 
    // correct selection i.e. us. 
    MKMapView* map = [self findMapView]; 
    [map selectAnnotation:self.annotation animated:NO]; 
    _selectionEnabled = YES; 

} 

mit

-(MKMapView*)findMapView; { 
    UIView* view = [self superview]; 
    while(!_mapView) { 
     if([view isKindOfClass:[MKMapView class]]) { 
      _mapView = (MKMapView*)view; 
     } else if ([view isKindOfClass:[UIWindow class]]){ 
      return nil; 
     } else{ 
      view = [view superview]; 
      if(!view) 
       return nil; 
     } 
    } 

    return _mapView; 
} 

Das alles scheint ohne und unten (wie Flackern zu arbeiten ich von anderen Lösungen gesehen habe. Es ist relativ einfach, aber es fühlt sich nicht richtig.

Jedermann Haben Sie eine bessere Lösung?

Antwort

1

Ich glaube nicht, dass Sie mit der Auswahl der Tracking-Ansicht der Karte zu affektieren.Wenn ich richtig interpretiere, was Sie wollen, sollten Sie in der Lage sein, acc vereinheitlichen Sie es mit nur der hitTest:withEvent: überschreiben und canShowCallout auf NO eingestellt. In setSelected: führen Sie Ihre Callout-Darstellung/Verschwinden Animation entsprechend aus. Sie sollten auch setHighlighted: überschreiben und die Anzeige Ihres benutzerdefinierten Callouts anpassen, falls sichtbar.