"Эта декларация функции не является прототипом" предупреждение в Xcode 9


при использовании Xcode 9, есть некоторые предупреждения компилятора говоря This function declaration is not a prototype. Это говорит о том, чтобы добавить void к телу метода,который разрешит его. Проблема, с которой я сталкиваюсь, заключается в том, что эти предупреждения также выбрасываются для system-API, например UIApplication делегат-методы:

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

теперь мне интересно, будут ли методы делегата по-прежнему работать на долгосрочной основе или Apple вставит void в более поздних бета-версиях iOS 11. Мне любопытно, потому что если я включаю void тело, Xcode будет жаловаться на несоответствие метод-селекторы (что имеет смысл). Кто-то испытывал ту же проблему до сих пор?

1 89

1 ответ:

объявление блока с пустой скобкой:

void (^)()

имеет ту же семантику, что и указатель функции с пустой скобкой:

void (*)()

это не значит, что нет аргументов. Это означает, что аргументы не заданы, поэтому он открывает путь к ошибкам, так как вы можете вызвать ее следующим образом:

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

при объявлении блоков без параметров всегда используйте:

void (^)(void)

Apple не делала это правильно везде, и они, вероятно, не исправляют это для старых API по причинам совместимости. Вам нужно будет сохранить это предупреждение там, пока вы не перейдете к новому API.

вы также можете отключить это предупреждение (-Wstrict-prototypes): enter image description here

или через #pragma (спасибо @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 не так хорош, как это должно быть.