Comment puis-je me empêcher d'utiliser accidentellement le pointeur d'un NSNumber quand je veux son intValue?

StackOverflow https://stackoverflow.com/questions/1898091

Question

Une caractéristique de Java que j'aime vraiment est autoboxing, dans lequel le compilateur convertit automatiquement entre les primitives et leurs classes wrapper.

J'écris une application de base de données en Objective-C / Cocoa, et je trouve frustrant de traiter avec mon entier attributs d'un programme. Voici pourquoi:

//img is a managed object that I have fetched

NSString* filename = [NSString stringWithFormat:@"image%d.png", [[img valueForKey:@"imageID"] intValue]];  

Si je suis d'oublier le message intValue, que je fais parfois, l'int qui est passé à stringWithFormat: est en fait la valeur du pointeur.

Le problème est que cela se produit totalement silencieux - aucune erreur du compilateur ou un avertissement. Parfois, je vais passer beaucoup trop de temps de débogage quand cette chose stupide, stupide est le problème.

Est-il possible de changer mon style de programmation ou mes paramètres du compilateur pour me empêcher de se faire prendre dans ce piège?

Modifier : Je n'étais pas clair sur le fait que l'exemple ci-dessus est juste un des nombreux endroits où j'ai des ennuis. Voici un autre exemple hypothétique qui n'a rien à voir avec les chaînes:

Entité CollegeClass a deux attributs entiers: courseNumber et enrollmentLimit. Disons que je veux comparer les numéros de cours:

//classFoo is a NSManagedObjects I've fetched
if ([[classFoo valueForKey@"courseNumber"] intValue] < 400) {
    NSLog(@"undergraduate class");
}

Ou même, supposons que je veuille calculer la limite d'inscription moyenne pour toutes les classes dans le département CS.

Était-ce utile?

La solution

  

... je suppose que veux calculer la limite d'inscription moyenne pour toutes les classes dans le département CS.

Ceci est facile à faire avec NSArray de et l'opérateur @avg de NSSet . Bien sûr, cela renvoie une NSNumber, qui vous met dans le problème # 2:

  

Disons que je veux comparer les numéros de cours:

//classFoo is a NSManagedObjects I've fetched
if ([[classFoo valueForKey@"courseNumber"] intValue] < 400) {
    NSLog(@"undergraduate class");
}

Je suppose que vous voulez dire que le problème que vous risquez omet le message intValue, comparant ainsi la id de l'objet NSNumber au int.

Le compilateur offre un avertissement pour ces comparaisons. Dans Xcode, ajoutez -Wextra à votre réglage de construction « Autres drapeaux C ». Pour plus d'options d'avertissement, consultez la liste complète des avertissements de GCC .

Autres conseils

Vous pouvez utiliser% @ pour convertir un NSNumber directement à une chaîne au lieu de% d.

Il fait prendre une classe à base NSObject et le convertir en une chaîne, je crois.

Ceci est applicable uniquement lorsqu'il s'agit de base de données, mais si vous utilisez MOGenerator pour générer des classes pour vos objets de base de données (que je vous conseille de faire de toute façon), vous pouvez alors utiliser des méthodes de -[propertyName]Value pour accéder directement à la valeur correcte pour les propriétés qui reviennent NSNumbers:

// These two methods are identical when called on a class 
// which was generated with MOGenerator
[[object imageID] intValue];
[object imageIDValue];

Activer l'avertissement « appelle à Typecheck printf / scanf », si elle est pas déjà. Cela ne veut pas actuellement Aide au formatage NS / de CFString, mais je l'ai déposé une demande d'amélioration de radar (x-radar: // problème / 7375186) pour cela. Vous êtes invités à déposer vos propres, bien sûr.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top