web-dev-qa-db-ja.com

「この関数宣言はプロトタイプではありません」というXcode 9の警告

Xcode 9を使用しているとき、This function declaration is not a prototypeというコンパイラの警告がいくつかあります。メソッド本体にvoidを追加することで解決できます。私が抱えている問題は、これらの警告がUIApplicationデリゲートメソッドのようなシステムAPIにも投げられることです。

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

これは次のようにして解決できます。

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

今、私はデレゲートメソッドがまだ長期的に機能するのか、それともiOS 11 Beta以降のバージョンではAppleがvoidを挿入するのかと思います。私が興味を持っているのは、void本体を含めると、Xcodeはメソッドセレクタの不一致について文句を言うでしょう(これは意味があります)。これまでに誰かが同じ問題を経験しましたか?

105
Hans Knöchel

空の括弧付きのブロック宣言:

void (^)()

空括弧付きの関数ポインタと同じ意味を持ちます。

void (*)()

議論がないという意味ではありません。これは、引数が指定されていないことを意味します。したがって、次の方法で呼び出すことができるので、バグへの道が開かれます。

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

パラメータなしでブロックを宣言するときは、常に次のようにしてください。

void (^)(void)

Appleはいたるところでそれを正しく行っていなかったし、互換性の理由からおそらく古いAPIのためにそれを修正していません。新しいAPIに移行するまでは、その警告をそこに残しておく必要があります。

その警告をオフにすることもできます(-Wstrict-prototypes): enter image description here

または#pragmaを使用する(Thanks @ 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

LLVMの議論 はこちら 、またはopenradarのバグをご覧ください。

APIの内部動作に変更はなかったことに注意してください。すべてのコードは引き続き機能します。私たちは、APIが本来あるべきほど良くないことを知るだけです。

230
Sulthan