9
votes

Mkannotationview et détection de robinet

J'ai un mkmapview . J'ai ajouté un uitapgesurerecognizer avec un seul robinet.

Je veux maintenant ajouter un mkannotationview sur la carte. Je peux appuyer sur l'annotation et MapView: MapView didiselectannotationView: voir incendies (où je vais ajouter une logique supplémentaire à afficher un UIView).

Le problème est maintenant lorsque j'appuyez sur l'annotation, le mkmapview Le geste du robinet est également des tirs.

Puis-je le mettre, donc si j'appuyez sur l'annotation, il ne répond que?


0 commentaires

6 Réponses :


-1
votes

Je ne suis pas sûr de savoir pourquoi vous auriez un uitapgesurerecognizer sur votre point de vue de la carte, affirmant que cela signifie évidemment que cela signifie évidemment que cela vous gâtera avec une fonctionnalité multitouch de votre carte.

Je vous suggère de jeter un coup d'œil et de jouer avec la propriété CancelStoucheSiView de uigesureecognizer (voir Documentation ). Je pense que cela pourrait résoudre votre problème. Assurez-vous de vérifier la documentation.


2 commentaires

Je dessine Mkpolygon sur la carte que l'utilisateur interagit avec. Le uitapesteurecognizer permet à l'utilisateur de sélectionner un objet polygone et de faire des choses avec elle.


OK, j'ai ajouté un uitapgeserecognzier au mkannotationview et définissez AnnultsTouchesInview . Il n'a pas empêché le reconnaissance du robinet sur le mkmapview du tir.



6
votes

Il pourrait y avoir une solution meilleure et plus propre, mais une seule façon de faire le tour est d'exploiter Hittest: Sans: dans le sélecteur reconnu de la gestes, par exemple.

Supposons que vous ayez ajouté un reconnaissance de gestes de robinet à votre _mapview xxx

Il ne couvre probablement pas tous les cas de bord mais il semble probablement Travailler assez bien pour moi.

Mise à jour (iOS> = 6.0)

Enfin, j'ai trouvé un autre type de solution qui a l'inconvénient d'être valide Pour iOS> = 6.0 : En fait, cette solution exploite le nouveau - (bool) gesturerecognizershouldbegin: (uigesurerecificateur *) gesturerecognizer ajouté au uIView s de cette façon xxx

c'est-à-dire, de l'iOS 6 en cours, il suffit de remplacer la méthode uiview dans chaque vue, le reconnaissance de geste doit ignorer.


6 commentaires

D'accord. Cela marche. Pas complètement sûr de ce que le mkannotationContainerview est cependant. Je m'attendais à ce que le uIview * v Hittest soit un MKAPView et a été surpris que ce ne soit pas. Merci beaucoup pour votre aide, je l'apprécie vraiment. Hors de curiosité, utilisez-vous Xcode? Je suis inconnu avec la deuxième en-tête de la méthode.


Si j'ai bien compris, le mkannotationcontainerview doit être une classe privée Apple dont l'instance doit contenir le MkmapView S annotationviews. Je suppose que c'est la raison pour laquelle le hittest le renvoie au lieu du mkmapview . En ce qui concerne votre curiosité, oui, j'utilise Xcode, probablement que la signature vous semble un peu étrange puisqu'elle est pertinente pour le langage C sur lequel obj c est en réalité basé.


HRM ... Si c'est une classe privée, Apple aurait des problèmes lorsque j'essaie de télécharger?


Je ne pense pas que votre application n'essaie pas de manipuler cet objet ou d'utiliser une API privée, cela devrait être correct. Pour plus de détails, allez à ce lien


Nous ne sommes pas censés savoir sur le MkannotationContainerview, que si Apple décide de changer cette API? Dès maintenant, ils ont réellement, c'est maintenant appelé MKNNewannotationContagerview.


@RODRIGORUIZ J'ai commencé à répondre à ce que ce soit peut-être la meilleure solution ... C'est pourquoi j'ai également édité ma réponse. Si vous avez une solution plus élégante et robuste, veuillez partager avec nous :)



2
votes

Pourquoi ne pas simplement ajouter UITAPGEGERECOnazer dans la vueFornotation, utilisez la réutilisation de l'annotation pour identifier quelle annotation il s'agit et dans la méthode de l'action TaphouseReCognizer, vous pouvez accéder à cet identifiant.

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
    MKAnnotationView *ann = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:@"some id"];

    if (ann) {
        return ann;
    }

    ann = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"some id"];
    ann.enabled = YES;

    UITapGestureRecognizer *pinTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(pinTapped:)];
    [ann addGestureRecognizer:pinTap];
}

-(IBAction)pinTapped:(UITapGestureRecognizer *)sender {
    MKAnnotationView *pin = (MKPinAnnotationView *)sender.view;
    NSLog(@"Pin with id %@ tapped", pin.reuseIdentifier);
}


0 commentaires

4
votes

Votre solution devrait utiliser le - (bool) gesturerecognizer: (uigesurerecognizer *) gesturerecognizer doit toucher (uitouch *) touchez code> méthode sur votre délégué.

Dans cette méthode, vous pouvez Vérifiez si le contact était sur l'une de vos annotations, et si oui, renvoie n ° code> de sorte que votre gesterecognizer code> n'est pas activé. p>

objectif-c : P>

private func getTappedAnnotations(touch touch: UITouch) -> [MKAnnotationView] {
    var tappedAnnotations: [MKAnnotationView] = []
    for annotation in self.mapView.annotations {
        if let annotationView: MKAnnotationView = self.mapView.viewForAnnotation(annotation) {
            let annotationPoint = touch.locationInView(annotationView)
            if CGRectContainsPoint(annotationView.bounds, annotationPoint) {
                tappedAnnotations.append(annotationView)
            }
        }
    }
    return tappedAnnotations
}

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
    return self.getTappedAnnotations(touch: touch).count > 0
}


0 commentaires

1
votes

AVERTISSEMENT! La solution acceptée et aussi celle ci-dessous est parfois buggy. Pourquoi? Parfois, vous appuyez sur Annotation, mais votre code agira comme si vous avez tapé la carte. Quelle est la raison de cela? Parce que vous avez tapé quelque part autour de votre cadre de votre annotation, comme + - 1 à 6 pixels autour, mais pas dans le cadre de la vue de l'annotation.

intéressant également est que lorsque votre code dira dans ce cas "Vous avez taché de la carte, pas d'annotation «La logique de code par défaut sur MKMAPView acceptera également ce robinet de fermeture, comme si c'était dans la région d'annotation et fera incendier la désactivation. P>

Vous devez donc refléter ce problème également dans votre code. Disons que ceci est le code par défaut: p>

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    CGPoint p = [gestureRecognizer locationInView:_customMapView];
    NSLog(@"point %@", NSStringFromCGPoint(p));

    UIView *v = [_customMapView hitTest:p withEvent:nil];

    if (![v isKindOfClass:[MKAnnotationView class]])
    {
       // annotation was not tapped, be we will accept also some
       // proximity touches around the annotations rects

       for (id<MKAnnotation>annotation in _customMapView.annotations)
       {
           MKAnnotationView* anView = [_customMapView viewForAnnotation: annotation];

           double dist = hypot((anView.frame.origin.x-p.x), (anView.frame.origin.y-p.y)); // compute distance of two points
           NSLog(@"%@ %f %@", NSStringFromCGRect(anView.frame), dist, [annotation title]);
           if (dist <= 30) return NO; // it was close to some annotation se we believe annotation was tapped
       }
       return YES;
    }

    return NO;
}


0 commentaires

0
votes

Ce serait beaucoup plus facile si nous voulons simplement tester les superviews du Touch.View dans le délégué gestuel: xxx


0 commentaires