Aviso “Esta declaração de função não é um protótipo” no Xcode 9

119

Ao usar o Xcode 9, existem alguns avisos do compilador dizendo This function declaration is not a prototype. Sugere adicionar voidao corpo do método, o que o resolverá. O problema que estou tendo é que esses avisos também são lançados para UIApplicationmétodos delegados semelhantes à API do sistema :

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

Isso pode ser resolvido da seguinte maneira:

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

Agora, estou me perguntando se os métodos delegados ainda funcionarão em longo prazo ou se a Apple inserirá o voidnas versões beta do iOS 11 posteriores. Estou curioso porque se eu incluir o voidcorpo, o Xcode reclamará sobre seletores de método incompatíveis (o que faz sentido). Alguém teve o mesmo problema até agora?

Hans Knöchel
fonte

Respostas:

251

A declaração de bloco com parênteses vazio:

void (^)()

tem a mesma semântica de um ponteiro de função com parênteses vazio:

void (*)()

Isso não significa que não haja argumentos. Isso significa que os argumentos não são especificados, portanto, abre o caminho para bugs, já que você pode chamá-lo das seguintes maneiras:

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

Ao declarar blocos sem parâmetros, sempre use:

void (^)(void)

A Apple não estava fazendo isso corretamente em todos os lugares e provavelmente não estava corrigindo isso para APIs antigas por motivos de compatibilidade. Você terá que manter esse aviso lá até que você mude para a API mais recente.

Você também pode desativar esse aviso ( -Wstrict-prototypes): insira a descrição da imagem aqui

ou usando #pragma(obrigado @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

Veja a discussão do LLVM aqui ou o bug no openradar .

Observe que não houve alteração no funcionamento interno das APIs, todo o código ainda funcionará. Saberemos apenas que a API não é tão boa quanto deveria ser.

Sulthan
fonte
5
Você também pode usar pragmas para remover o aviso ao implementar a API iOS: #pragma clang diagnostic push #pragma clang diagnostic Ignorado "-Wstrict-prototypes" - (void) application: (UIApplication *) application handleActionWithIdentifier: (NSString *) identifier forRemoteNotification: (NSDictionary *) userInfo withResponseInfo: (NSDictionary *) responseInfo target="Handler: (void (^) ()) completedHandler {#pragma clang diagnostic pop
davidisdk
1
Recebi cerca de 20 avisos sobre isso com a API JBChartView. É bom poder desligá-los até que decidam atualizar para o Swift 4.
Edison
7
@tymac Este é um aviso objc. Não tem nada a ver com Swift.
Sulthan de
> "Ao declarar blocos sem parâmetros, sempre use (void)" <Você pode adicionar como deve ser a aparência no código? Como uma alternativa para void (^)()orvoid (*)()
pkamb
2
@pkamb Quando o bloco não tomar quaisquer parâmetros (ie void(^)()), incluir explicitamente voidnos parênteses: void(^)(void).
Ben Stock