10
votes

Se débarrasser de "" NsObject 'peut ne pas répondre à "-Somemethod" "Avertissement

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 inférieur . 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? xxx


5 commentaires

En outre, si je reçois la terminologie "sélecteur" mal, veuillez me corriger. :)


Ne pas 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 qui prend une chaîne de format (comme StringwithFormat :), assurez-vous de passer un format .


4 Réponses :


4
votes

Il suffit de lancer votre NsObject à un Nstring avant d'appeler la fonction: xxx


3 commentaires

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 , 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 * .



16
votes

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]);
    }
}


5 commentaires

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 comme type de données pour cela, il se plaint de conserver / de libérer (et d'autres fonctions NsObject) ne sont pas trouvées dans le protocole. Cela suppose simplement que le protocole définira chaque méthode appelée sur l'objet. Fonctionne bien sinon - cette situation particulière me rend fou, cependant!


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.



6
votes

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
    }
}


1 commentaires

Ah, cela semble être une bonne façon de le faire. Merci pour la réponse.



1
votes

Casting en tant que ID supprimé l'avertissement.

if ([self.content respondsToSelector:@selector(setDelegate:)])
{
    [(id)self.content setDelegate:nil];
}


0 commentaires