2015-03-27 2 views
2

Si j'ai des méthodes telles que:type sécurité paramètre méthode Objective-C

- (BOOL)isValidRow:(NSDictionary*)contentVersionRow 

avons-nous vraiment vérifier en permanence comme celui-ci au début de la méthode

if(![contentVersionRow isKindOfClass:[NSDictionary class]]) { 
    // Handle unusual situation - probably return NO in this case 
} 

à mettre en œuvre vraiment bon type-sécurité à l'intérieur des méthodes Objective-C? Parce qu'en théorie le paramètre n'est pas garanti pour pointer vers un objet NSDictionary, est-ce correct?

EDIT: Donc, les réponses semblent indiquer que nous ne devrions pas vérifier cela, mais alors quelle est la différence entre vérifier cela et vérifier le paramètre nil, ce que je suppose que nous devrions faire? Ou ne devrions-nous pas vérifier non plus, si ce n'est normalement pas prévu? Les deux cas couvrent la situation d'un appelant mal se comporter.

+1

C'est vraiment la responsabilité de l'appelant de faire sûr qu'ils passent le bon type à la méthode. – dan

+0

Habituellement, l'EDI xCode lui-même commence à vous donner un avertissement ou une erreur lorsque l'appelant tente de modifier le paramètre. – itsji10dra

+0

Il vous suffit de vérifier pour nil, IDE vous préviendra s'il y a une discordance et si l'objet n'est pas en mesure de convertir – Vig

Répondre

3

Tout comme dans C vous avez affaire à des pointeurs en Objective-C. Donc dire NSDictionary * signifie simplement "voici un pointeur vers une adresse mémoire qui contient une instance de NSDictionary".

Exemple:

#import <Foundation/Foundation.h> 

@interface Test : NSObject 
- (void)useDictionary:(NSDictionary *)dictionary; 
@end 

@implementation Test 
- (void)useDictionary:(NSDictionary *)dictionary 
{ 
    NSLog(@"Keys: %@", [dictionary allKeys]); 
} 
@end 

int main(int argc, char *argv[]) { 
    @autoreleasepool { 
     Test *test = [[Test alloc] init]; 

     // 1: This works fine 
     [test useDictionary:@{@"key": @"value"}]; 

     // 2: This will cause a compiler warning (or error depending on the options passed to the compiler) 
     [test useDictionary:@"not a dictionary"]; 

     // 3: This will compile without any warnings 
     [test useDictionary:(NSDictionary *)@"not a dictionary"]; 
    } 
} 

Les 2e et 3e exemples provoqueront un plantage du programme lors de l'exécution. Donc, si vous voulez transmettre des choses incorrectes à des méthodes, vous pouvez le faire. Habituellement, Xcode vous avertira si vous avez une incompatibilité de type.

Mise à jour à propos de la vérification nil: Si c'est une mauvaise utilisation de l'API pour passer nil à votre méthode, alors lancez une exception. C'est ce que les exceptions sont dans Objective-C: pour attraper programmation erreurs, de ne pas gérer les problèmes d'exécution attendus (comme un réseau inaccessible). Si votre méthode peut simplement échouer silencieusement si nil est passé ou la gérer de manière sensée, faites-le à la place. Par exemple si vous avez une méthode addValue:(NSNumber *)number qui ajoute la valeur donnée à une somme alors ce ne serait pas un gros problème si quelqu'un l'appelait avec nil: N'ajoutez rien du tout :)

+0

Si je veux exposer une API qui est garantie * à ne pas échouer * dans le code de méthode de mon API (ie ne peut échouer avec une exception non gérée) même si les appelants mal intentionnés envoient des pointeurs de mauvais type ... quel est le meilleur moyen d'atteindre cet objectif?Je cherche à rendre les méthodes solides, indépendantes de ce que n'importe quel appelant peut leur lancer. Est-ce quelque chose qui n'est qu'un objectif irréaliste dans un langage dynamiquement typé? –

+2

Je pense que c'est un objectif irréaliste. Pensez-y de cette façon: Comment puis-je faire une voiture qui ne peut pas être utilisée pour piétiner les piétons? Comment puis-je fabriquer un couteau qui ne peut pas être utilisé pour poignarder quelqu'un? Si quelqu'un veut abuser intentionnellement de votre API, il ne devrait pas être surpris s'il explose. Parfois, il n'y a aucun moyen sensé de récupérer à partir d'un appel d'API gravement mal utilisé: Ma méthode "addEventToCalendar" attend un objet "MyEvent", mais je passe dans une instance de UIView. Eh bien, ça va exploser, il n'y a pas moyen de gérer ça d'une manière qui a du sens. Il y a une grave erreur de programmation, donc ça devrait tomber en panne. –

3

Oui, mais vous ne devriez pas. Obj-C est un langage dynamique, il appartient donc à chaque objet de déterminer s'il répond à une méthode donnée. C'est un mauvais style de vérifier la classe d'un objet. Au lieu de cela, si vous voulez vérifier qu'un objet supporte un sélecteur, vous devez utiliser -respondsToSelector:, mais seulement si vous gérez des objets qui ne répondent pas à ce sélecteur.

+1

Exactement, il existe des cas spécifiques où vous devez vérifier le type (par exemple, lors de l'analyse d'un fichier JSON), mais c'est rare. – Sulthan