2010-01-15 3 views
3

J'ai mes données dans un objet NSDictionary où les clés sont des CGPoints convertis en NSValues ​​et les objets sont des UIColors . Voici la méthode que je utilise pour renvoyer un objet du dictionnaire:Échec de l'énumération rapide sur NSDictionary avec "[Waypoint countByEnumeratingWithState: objects: count:]: sélecteur non reconnu envoyé à instance ..."

- (UIColor*) getTemperatureColor2 { 
    NSDictionary* temperatureColorMap = [Weather getTemperatureColorMap]; 

    for(id key in temperatureColorMap) { 
     CGPoint point = [key CGPointValue]; 
     if ((int)roundf(self.temperature_celsius) >= (int)roundf(point.x) ) { 
      if ((int) roundf(self.temperature_celsius) <= (int) roundf(point.y)) { 
       return [temperatureColorMap objectForKey:key]; 
      } 
     }  
    } 

    return [UIColor blackColor];  
} 

Ceci est la méthode getTemperatureColorMap, mis en œuvre dans cette même classe (Météo):

+ (NSDictionary*) getTemperatureColorMap { 
    static NSDictionary* temperatureColorMap = nil; 

    if (temperatureColorMap == nil) { 
     temperatureColorMap = [[[NSDictionary alloc] initWithObjectsAndKeys: 
          RGB2UIColor(0x0E09EE), [NSValue valueWithCGPoint: CGPointMake(-99, -8)], 
          RGB2UIColor(0xB85FC), [NSValue valueWithCGPoint: CGPointMake(-7, -3) ], 
          RGB2UIColor(0x0BDCFC), [NSValue valueWithCGPoint: CGPointMake(-2, 2) ], 
          RGB2UIColor(0x1BBA17), [NSValue valueWithCGPoint: CGPointMake(3, 7) ], 
          RGB2UIColor(0x45F90C), [NSValue valueWithCGPoint: CGPointMake(8, 12) ], 
          RGB2UIColor(0xF9F60C), [NSValue valueWithCGPoint: CGPointMake(13, 17) ], 
          RGB2UIColor(0xF9B20C), [NSValue valueWithCGPoint: CGPointMake(18, 22) ], 
          RGB2UIColor(0xF9780C), [NSValue valueWithCGPoint: CGPointMake(23, 27) ], 
          RGB2UIColor(0xFE3809), [NSValue valueWithCGPoint: CGPointMake(28, 32) ], 
          RGB2UIColor(0xFE0909), [NSValue valueWithCGPoint: CGPointMake(33, 99) ], nil] autorelease]; 
    } 

    return temperatureColorMap; 
} 

J'appelle getTemperatureColor2 dans un des boucle (passant par tous les waypoints), qui est tout dans la méthode drawRect. Un waypoint contient un objet météo. Lorsque la vue est chargée, la méthode drawRect est appelée deux fois (j'en ai besoin pour un effet). La première fois, tout est bien, mais la deuxième fois, dès que le code atteint l'énumération rapide pour boucle j'obtenir une exception:

2010-01-15 11:40:42.224 AppName[1601:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[Waypoint countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x856d170' 

Maintenant, je ne sais pas comment l'erreur est Waypoint car il est un NSDictionary que Je suis en train de parcourir. Aussi, je ne comprends absolument pas pourquoi il faut un autre appel à drawRect pour que l'itération échoue!

Répondre

6

Vous voulez exécuter l'énumération rapide sur les touches dans le dictionnaire comme celui-ci:

for(NSValue *key in [temperatureColorMap allKeys]) 

MISE À JOUR
Bien que ma suggestion rend l'objet plus clair, il est certainement pas la cause d'exception que vous voient (je me rends compte maintenant que NSDictionary implémente l'énumération rapide et il doit être sur le tableau de clés). Je pense maintenant qu'il pourrait s'agir d'une erreur de mémoire puisque vous autoreleasing le dictionnaire (mais la référence statique ne sera pas définie à zéro quand il est libéré), mais je ne peux pas reproduire l'exception même en exécutant votre méthode plusieurs fois. La seule différence entre mon code et le vôtre est que j'ai changé l'appel à RGB2UIColor en un appel à une méthode objective-C à la place.
Vous n'avez pas fourni son implémentation, mais puis-je supposer qu'il est capable de renvoyer un objet UIColor objectif-C correct?

+0

Je pense que vous pourriez avoir raison, je suis toujours perplexe par la façon de gérer la gestion de la mémoire dans certaines situations. Je sais que je dois libérer la temperatureColorMap, mais comment savoir quand il n'est plus nécessaire? Où dois-je envoyer le message de libération dans le code? – Leonard

+0

Généralement, si vous avez besoin d'un objet pendant la durée de vie d'un autre objet (comme un contrôleur de vue), vous en feriez une variable d'instance et/ou une propriété de l'autre objet (et libérez-le dans le dealloc de l'autre objet méthode). – gerry3

+0

Je cours mon code encore et j'ai eu une erreur BAD_EXEC - je suis désolé, je dois avoir confondu quelque chose. Au lieu d'autoeleasing le temperatureColorMap je le libère maintenant manuellement dans getTemperatureColor2 après que la boucle for soit faite - ainsi c'est le point dans le code où la carte de température n'est plus nécessaire. Travaux! Je suis familier avec la gestion des variables d'instance, je ne sais généralement pas quoi faire avec les objets qui sont créés quelque part dans le code, puis transmis comme arguments à une autre méthode dans une autre classe. – Leonard

3

Je pensais que la syntaxe de tableau par défaut pour le dénombrement rapide fonctionnerait automagiquement pour NSDictionary:

for(MyClass* instance in dictionary){ // <- this works for NSArray 
    // process instance here 
} 

Cependant, cela semble donner les deux objets (instances de MyClass) et clés de le dictionnaire (instances de NSString). Mon application était en panne à cause de MyClass méthodes étant appelées NSString. Donc j'ai fini par faire ceci:

Questions connexes