J'apprends ObjectIVec et j'ai couru dans un problème relatif à l'introspection. Fondamentalement, je suis en boucle à travers un tableau d'objets et je déterminerai s'ils acceptent le sélecteur code> inférieur code>. S'ils le font, j'appelle ce sélecteur sur l'objet. Après avoir veillé à ce que l'objet réponde à ce sélecteur, je l'appelle. Cependant, lorsque je le fais, je reçois cet avertissement: "Avertissement:" NsObject; peut ne pas répondre à "-LowerCasestring" "
Bien que le code fonctionne bien comme écrit, je voudrais ne pas obtenir l'avertissement. Je suppose qu'il y a un moyen "droit" de s'assurer que je ne reçois pas cet avertissement (c'est-à-dire sans simplement transformer des avertissements). Des idées? P>
4 Réponses :
Il suffit de lancer votre NsObject à un Nstring avant d'appeler la fonction:
Mais que se passe-t-il si l'objet ne prend pas en charge tous les sélecteurs que Nstring prend en charge? Mon oop-sens me dit que ce serait mauvais. Je vérifie juste un sélecteur, quelle que soit la superclasse auquel il appartient.
Eh bien, vous supposez que -LowsSestring renvoie une nstring, car c'est ce que NSLog attend pour la chaîne de format. Si, pour une raison quelconque, il ne renvoie pas une nstring, alors vous passez à autre chose qu'un nstring comme chaîne de format, et NSLOG s'étouffera dessus.
La manière la plus sûre serait d'obtenir le moindrecasestring code>, stockez-le dans une variable et testez s'il s'agit d'une sorte de nstring. Vous n'avez probablement pas besoin d'être ce paranoïaque, cependant, et si vous n'allez pas être, vous pourriez aussi bien déclarer la variable comme ou jeter la valeur de retour à, nstring * code>.
Vous pouvez également utiliser ID code> qui est n'importe quel type d'objet. for (id element in myArray) {
if ([element respondsToSelector:lowercaseSelector]) {
NSLog([element lowercaseString]);
}
}
Je pensais que NsObject serait la bonne, mais, en effet, je semble une meilleure façon de le faire.
Tant que vous n'avez pas besoin d'appeler de conserver ou de libérer sur l'élément ;-)
Si vous avez un objet conforme à un protocole et que vous utilisez ID
La solution de contournement est de rendre tous vos protocoles conformes à
Très gentil ... J'essayais de comprendre comment supprimer l'avertissement avec une directive de compilateur, mais c'est bien mieux.
Que diriez-vous d'utiliser performselector: code>? SEL lowercaseSelector = @selector(lowercaseString);
for (NSObject *element in myArray) {
if ([element respondsToSelector:lowercaseSelector]) {
NSLog([element performSelector:lowercaseSelector]); // No warning
}
}
Ah, cela semble être une bonne façon de le faire. Merci pour la réponse.
Casting en tant que ID supprimé l'avertissement.
if ([self.content respondsToSelector:@selector(setDelegate:)])
{
[(id)self.content setDelegate:nil];
}
En outre, si je reçois la terminologie "sélecteur" mal, veuillez me corriger. :)
Ne pas I> Passez des chaînes non constantes à NSLog. Il y a un risque de sécurité. Vous pensez peut-être que vous êtes en sécurité dans ce cas, mais n'entrez pas l'habitude de cela. Vous finirez inévitablement de le faire dans un cas qui ouvre un trou de sécurité.
Avez-vous un lien avec plus d'informations sur ce trou de sécurité? Je suis certainement intéressé à lire davantage à ce sujet.
Vous devez toujours passer une chaîne de format pour la première Arg de NSLog. Si l'un des éléments de votre matrice contient des caractères de formatage, NSLOG essaiera de lire les arguments associés, mais vous n'aurez pas transmis aucun. Écrivez plutôt NSLOG (@ "% @", [Élément BASTERCASESTRING]) ;.
Ce n'est pas simplement un trou de sécurité, c'est un crash potentiel. Si la chaîne contient% s ou% @ Il faudra traiter indistinctement les octets aléatoires sur la pile en tant que pointeur, leur déférence et si vous avez utilisé% @, envoyez-y le message [auto-description]. Comme le dit Jim, et pour toute fonction i> qui prend une chaîne de format (comme StringwithFormat :), assurez-vous de passer un format i>.