Supprimer “’…’ est obsolète” lors de l’utilisation de respondsToSelector

Je soutiens 10.4+ en sélectionnant l’API la plus courante à 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 les removeItemAtPath:error: utiliseront removeItemAtPath:error: et 10.4 utilisera removeFileAtPath:handler: Génial, mais j’ai toujours des avertissements du compilateur pour les anciennes méthodes:

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

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

Sinon, existe-t-il un moyen de baliser cette ligne pour qu’elle soit ignorée pour -Wdeprecated-declarations ?


Après avoir vu certaines des réponses, permettez-moi de préciser que confondre le compilateur pour ne pas savoir ce que je fais n’est pas une solution valable.

J’ai trouvé un exemple dans le manuel d’utilisation 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 } 

Vous pouvez déclarer un fichier distinct destiné à appeler des méthodes obsolètes et définir les indicateurs de compilation 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 dans vos fichiers source réels.

Je ne suis pas sûr si clang est assez intelligent pour intercepter cela, mais si ce n’est pas le cas, vous pouvez utiliser performSelector:withObject:withObject: ou créer et invoquer un object NSInvocation.

Vous pouvez simplement fileManager en id – les ids peuvent faire référence à n’importe quel object Objective-C, donc le compilateur n’est pas censé vérifier les méthodes appelées sur un:

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

ne devrait pas déclencher d’avertissement ou d’erreur.

Bien sûr, cela soulève d’autres problèmes, à savoir que vous perdez toute vérification au moment de la compilation pour les méthodes appelées sur l’ id . Donc, si vous avez mal orthographié votre nom de méthode, etc., il ne sera pas capturé tant que cette ligne de code n’est pas exécutée.

Si vous considérez que toute forme de “confusion” du compilateur est une solution invalide, vous devrez probablement respecter l’avertissement. (Dans mon livre, si vous vous demandez comment vous débarrasser d’un avertissement, il est déconseillé de regarder un cheval dans la bouche et de dire que quelque chose est invalide simplement parce qu’il ne vous semble pas normal.)

Les réponses qui fonctionnent à l’exécution impliquent de masquer l’opération qui se produit avec la répartition dynamic afin que le compilateur ne se plaint pas de l’appel obsolète. Si vous n’aimez pas cette approche, vous pouvez désactiver l’option “Avertir à propos des fonctions obsolètes” dans votre projet Xcode ou vos parameters cibles, mais c’est généralement une mauvaise idée. Vous souhaitez connaître les API obsolètes, mais dans ce cas, vous souhaitez les utiliser sans avertissement. Il y a des manières faciles et faciles de le faire, et il y a de fortes chances que vous les considériez toutes comme «non valides», mais cela ne les empêche pas d’être efficaces, même correctes. 😉

Un moyen possible d’éviter les avertissements tout en sélectionnant à l’exécution est d’utiliser directement objc_msgSend() :

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

C’est ce que fait le runtime d’Objective-C sous les couvertures , et devrait accomplir le résultat souhaité avec un minimum de tracas. Vous pouvez même laisser la ligne originale commentée ci-dessus pour plus de clarté. Je sais que la documentation dit: “Le compilateur génère des appels à la fonction de messagerie. Vous ne devriez jamais l’appeler directement dans le code que vous écrivez.” Vous seul devez décider quand il est acceptable de plier les règles.