56 votes

La suppression de "'…' est obsolète" lors de l'utilisation de respondsToSelector

Je suis l'appui de 10,4+ en choisissant la plus actuelle de l'API à l'exécution:

if ([fileManager respondsToSelector:@selector(removeItemAtPath:error:)])
    [fileManager removeItemAtPath:downloadDir error:NULL];
else
    [fileManager removeFileAtPath:downloadDir handler:nil];

Dans ce cas, 10.5 et utilisera removeItemAtPath:error: et 10,4 utilisera removeFileAtPath:handler:. Super, mais j'ai toujours les avertissements du compilateur pour les vieilles méthodes:

warning: 'removeFileAtPath:handler:' is deprecated [-Wdeprecated-declarations]

Est-il une syntaxe if([… respondsToSelector:@selector(…)]){ … } else { … } qui laisse le compilateur Clang) de ne pas avertir sur cette ligne?

Si non, est-il un moyen de tag que la ligne sera ignorée pour -Wdeprecated-declarations?


Après avoir vu certaines réponses, permettez-moi de préciser que la confusion entre le compilateur en ne sachant pas ce que je fais n'est pas une solution valable.

117voto

Sidnicious Points 15187

J'ai trouvé un exemple dans le manuel de l'utilisateur du compilateur Clang qui me permet d'ignorer l'avertissement:

 if ([fileManager respondsToSelector:@selector(removeItemAtPath:error:)]) {
    [fileManager removeItemAtPath:downloadDir error:NULL];
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
    [fileManager removeFileAtPath:downloadDir handler:nil];
#pragma clang diagnostic pop
}
 

8voto

kperryua Points 6905

Vous pouvez déclarer un fichier distinct désigné pour appeler des méthodes obsolètes et définir les indicateurs du compilateur par fichier dans Xcode pour ignorer -Wdeprecated-declarations . Vous pouvez ensuite définir une fonction factice dans ce fichier pour appeler les méthodes obsolètes et éviter ainsi les avertissements contenus dans vos fichiers source réels.

6voto

Martin Gordon Points 19587

Je ne sais pas si clang est assez intelligent pour saisir cela, mais si ce n'est pas le cas, vous pouvez essayer d'utiliser performSelector:withObject:withObject: ou de créer et d'appeler un objet NSInvocation.

5voto

Matt Ball Points 4929

Vous pourriez jeter fileManager d'un id - ids sont en mesure de se référer à toute Objective-C objet, de sorte que le compilateur n'est pas censé vérifier les méthodes qui sont appelées l'une:

[(id)fileManager removeItemAtPath:downloadDir error:NULL];

ne pas soulever des avertissements ou des erreurs.

Bien sûr, cela soulève d'autres problèmes, à savoir, vous perdez tout moment de la compilation de la vérification pour les méthodes appelées sur l' id. Donc, si vous avez mal orthographié vous le nom de la méthode, etc, il ne sera pas pris jusqu'à ce que la ligne de code est exécutée.

3voto

Quinn Taylor Points 29688

Si vous envisager toute forme de "confusion", le compilateur être une solution non valide, vous allez probablement avoir à vivre avec l'avertissement. (Dans mon livre, si vous vous demander comment se débarrasser d'un avertissement, il n'est pas judicieux de regarder un cheval de cadeau dans la bouche et de dire quelque chose n'est pas valide simplement parce qu'il ne regarde pas comme vous le souhaitez.)

Les réponses que le travail au moment de l'exécution impliquent de masquage de l'opération qui se passe avec répartition dynamique de sorte que le compilateur ne se plaignent pas du type d'appel obsolète. Si vous n'aimez pas cette approche, vous pouvez désactiver l'option "Avertir à Propos Obsolète Fonctions" dans votre projet Xcode ou les paramètres de la cible, mais c'est généralement une mauvaise idée. Vous voulez savoir sur l'Api obsolète, mais dans ce cas, vous voulez l'utiliser sans avertissement. Il y a le facile et le difficile façons de le faire, et les chances sont que vous considéreriez comme tous les "non valide" dans une certaine forme, mais cela ne les empêche pas d'être efficace, même correcte. ;-)

Une solution possible pour éviter les mises en garde pourtant toujours sélectionner au moment de l'exécution est d'utiliser objc_msgSend() directement:

objc_msgSend(fileManager, @selector(removeFileAtPath:error:), downloadDir, nil];

C'est ce que l'Objective-C runtime sous les couvertures, de toute façon, et devrait atteindre le résultat que vous voulez avec un minimum de tracas. Vous pouvez même laisser la ligne d'origine, a commenté ci-dessus pour plus de clarté. Je sais que la documentation dit, "Le compilateur de générer des appels à la fonction de messagerie. Vous ne devriez jamais l'appeler directement dans le code que vous écrivez." Vous seul avez à décider quand il est d'accord pour contourner les règles.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X