web-dev-qa-db-fra.com

Avertissement "Cette déclaration de fonction n'est pas un prototype" dans Xcode 9

Lors de l’utilisation de Xcode 9, certains avertissements du compilateur indiquent This function declaration is not a prototype. Il suggère d'ajouter void au corps de la méthode, ce qui le résoudra. Le problème que je rencontre est que ces avertissements sont également émis pour les API système telles que UIApplication delegate-methods:

- (void)application:(UIApplication *)application
    handleActionWithIdentifier:(NSString *)identifier
         forRemoteNotification:(NSDictionary *)userInfo
              withResponseInfo:(NSDictionary *)responseInfo
             completionHandler:(void (^)())completionHandler

Cela pourrait être résolu comme suit:

- (void)application:(UIApplication *)application
    handleActionWithIdentifier:(NSString *)identifier
         forRemoteNotification:(NSDictionary *)userInfo
              withResponseInfo:(NSDictionary *)responseInfo
             completionHandler:(void (^)(void))completionHandler

Maintenant, je me demande si les méthodes de délégation fonctionneront toujours sur le long terme ou si Apple insérera la void dans les versions ultérieures iOS 11 Bêta. Je suis curieux car si j'inclus le corps void, Xcode se plaindra de la non-concordance des sélecteurs de méthode (ce qui est logique). Quelqu'un at-il rencontré le même problème jusqu'à présent?

109
Hans Knöchel

La déclaration de bloc avec des parenthèses vides:

void (^)()

a la même sémantique qu'un pointeur de fonction avec des parenthèses vides:

void (*)()

Cela ne signifie pas qu'il n'y a pas d'arguments. Cela signifie que les arguments ne sont pas spécifiés, donc cela ouvre la voie aux bogues puisque vous pouvez l'appeler des manières suivantes:

void (^block)() = ...
block();
block(10);
block(@"myString");

Lors de la déclaration de blocs sans paramètre, utilisez toujours:

void (^)(void)

Apple ne le faisait pas correctement partout et ils ne corrigent probablement pas cela pour les anciennes API pour des raisons de compatibilité. Vous devrez conserver cet avertissement jusqu'à ce que vous passiez à la nouvelle API.

Vous pouvez également désactiver cet avertissement (-Wstrict-prototypes): enter image description here

ou en utilisant #pragma (merci @ davidisdk ):

#pragma clang diagnostic Push
#pragma clang diagnostic ignored "-Wstrict-prototypes"

- (void)application:(UIApplication *)application
handleActionWithIdentifier:(NSString *)identifier
forRemoteNotification:(NSDictionary *)userInfo
   withResponseInfo:(NSDictionary *)responseInfo
  completionHandler:(void (^)())completionHandler {

}
#pragma clang diagnostic pop

Voir la discussion sur LLVM ici ou le bogue sur openradar .

Notez que rien n’a changé dans le fonctionnement interne des API, tout le code fonctionnera toujours. Nous saurons seulement que l'API n'est pas aussi bonne qu'elle devrait l'être.

236
Sulthan