performSelector may cause a leak because its selector is unknown
Céroce
Membre, Modérateur
Je suis tombé sur un problème intéressant, autant le partager avec vous.
Je suis en train d'écrire un test unitaire sur un UITableViewController. La table présente une liste de "Decks". Le TableViewController est contenu dans un navigation controller, et possède à gauche un bouton Plus. Le toucher doit ajouter un Deck. Voici le test:
Au départ, decks.count vaut 0.
Je récupère l'action associée au bouton de gauche, et la déclenche.
decks.count doit alors valoir 1.
Malheureusement, j'obtiens le warning "performSelector may cause a leak because its selector is unknown".
Pour l'instant, j'ai désactivé le warning en utilisant un #pragma. D'autres suggestions ?
Je suis en train d'écrire un test unitaire sur un UITableViewController. La table présente une liste de "Decks". Le TableViewController est contenu dans un navigation controller, et possède à gauche un bouton Plus. Le toucher doit ajouter un Deck. Voici le test:
<br />
- (void) testAddsACardOnLeftButtonAction<br />
{<br />
UIBarButtonItem *leftButton = controller.navigationItem.leftBarButtonItem;<br />
[controller performSelector:leftButton.action withObject:leftButton];<br />
STAssertEquals(decks.count, (NSUInteger)1, @"Should have an extra deck.");<br />
}<br />
Au départ, decks.count vaut 0.
Je récupère l'action associée au bouton de gauche, et la déclenche.
decks.count doit alors valoir 1.
Malheureusement, j'obtiens le warning "performSelector may cause a leak because its selector is unknown".
Pour l'instant, j'ai désactivé le warning en utilisant un #pragma. D'autres suggestions ?
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
En fait c'est parce que comme tu demandes d'exécuter un @selector dont il ne peut pas deviner le nom à la compilation, il ne sait pas quelles conventions de nommage et donc de gestion mémoire ce selector respecte.
En fait le warning est là car si le @selector retourné par leftButton.action était un @selector(newObject ou @selector(objectCopy, ton code générerait un leak, et le compilateur n'a aucun moyen de savoir si c'est le cas ou pas, donc il t'alerte que le risque est là mais qu'il ne peut pas en être sûr (d'où le "MAY").
Bien entendu, toi tu sais que, étant donné que ton @selector dans ce cas c'est une action d'un bouton, c'est forcément une méthode qui suit une convention autorelease. Et donc que tu n'auras pas de leak. Mais lui ne peut pas le deviner.
En effet la solution la plus propre je pense c'est désactiver le warning autour de ce code, à coup de "#pragma clang diagnostic push/ignored/pop".
Bon, je fais juste taire le warning, alors /thumbsup.gif' class='bbc_emoticon' alt='' />
(puisqu'aucun objet n'est renvoyé, pas de risque de fuite).
Bien sûr ça ne marchera que si l'action de ton leftButton prend bien le paramètre sender. Mais tu sais qu'on a plusieurs moyens d'écrire une IBAction pour un bouton, on peut ne pas lui passer de paramètre, ou lui passer le paramètre sender, ou lui passer le paramètre sender et event, c'est au choix... Donc idéalement si tu veux être robuste faudrait penser à tester tous les cas (et ce que tu fasses performSelector et désactive le warning ou que tu fasses methodForSelector, d'ailleurs)