2010-07-22 12 views
1

J'ai un tableau de MKAnnotation objets appelés arrAnnotations. Je veux choisir l'une des annotations avec la même coordonnée que celle stockée dans un objet CLLocation appelé "newLocation".Pourquoi NSPredicate ne fonctionne-t-il pas?

J'essaie d'utiliser un NSPredicate, mais cela ne fonctionne pas.

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SELF.coordinate == %f)", newLocation.coordinate]; 
NSArray* filteredArray = [arrAnnotations filteredArrayUsingPredicate:predicate]; 
[self.mapView selectAnnotation:[filteredArray objectAtIndex:0] animated:YES]; 

L'élément filteredArray contient toujours des objets zéro.

J'ai aussi essayé ce qui suit, qui ne fonctionnent pas non plus

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(coordinate == %f)", newLocation.coordinate]; 

et

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(coordinate > 0)"]; 

et

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(coordinate.latitude == %f)", newLocation.coordinate.latitude]; 

Les deux derniers accident de l'application, le troisième avec un NSInvalidArgumentException pour [NSConcreteValue compare:] et le quatrième, parce que latitude est pas key-value-coding-compliant (je suppose que c'est parce que coordonnée est juste un c-struct et pas un NSObject?).

Comment puis-je faire fonctionner cela avec NSPredicate? Quelqu'un peut-il me donner un lien vers un document qui montre comment Predicates fonctionne sous le capot? Je ne comprends pas ce qu'ils font réellement, même si j'ai lu et compris la plupart des Predicate Programming Guide d'Apple. Est-ce que rechercher un grand tableau avec des prédicats est plus efficace que simplement le boucler avec une construction for ... in? Si oui/non, pourquoi?

+0

Vous ne pouvez pas interpréter une structure comme un «double». Vous pouvez obtenir quelque chose avec 'NSLog (@"% f ", aCoordinate)' mais ce comportement n'est pas défini et peut conduire à des plantages etc. Comme 'NSPredicate' ne fonctionne pas avec C-structs, vous pouvez utiliser des tests explicites pour le moment à moins que quelqu'un ayant de l'expérience dans CoreLocation connaisse une meilleure alternative. –

Répondre

6

protocole MKAnnotation de coordonnées propriété est un CLLocationCoordinate2Dstruct, donc il est interdit dans la syntaxe de format NSPredicate selon la Predicate Format String Syntax

Vous pouvez utiliser NSPredicatepredicateWithBlock: au lieu d'accomplir ce que vous essayez de faire, mais il faut faire attention avec CLLocationCoordinate2D et comment le comparer pour l'égalité.

CLLocationCoordinate2D propriété de » latitude et longitude sont CLLocationDegrees type de données, ce qui est une double par définition.

Avec une recherche rapide, vous pouvez trouver plusieurs exemples de problèmes auxquels vous seriez confrontés lors de la comparaison de valeurs à virgule flottante pour l'égalité. Quelques bons exemples peuvent être trouvés here, here et here. Compte tenu de tout cela, je crois que l'utilisation du code ci-dessous pour votre prédicat pourrait résoudre votre problème.

NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) { 

    id<MKAnnotation> annotation = evaluatedObject; 

    if (fabsf([annotation coordinate].latitude - [newLocation coordinate].latitude) < 0.000001 
      && fabsf([annotation coordinate].longitude - [newLocation coordinate].longitude) < 0.000001) { 
     return YES; 
    } else { 
     return NO; 
    } 

}];