Advertencia "Esta declaración de función no es un prototipo" en Xcode 9

119

Al usar Xcode 9, hay algunas advertencias del compilador que dicen This function declaration is not a prototype. Sugiere agregar voidal cuerpo del método, que lo resolverá. El problema que tengo es que esas advertencias también se lanzan para UIApplicationlos métodos de delegado del sistema API :

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

Esto podría resolverse de la siguiente manera:

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

Ahora me pregunto si los métodos delegados seguirán funcionando a largo plazo o si Apple los insertará voiden versiones posteriores de iOS 11 Beta. Tengo curiosidad porque si incluyo el voidcuerpo, Xcode se quejará de que los selectores de métodos no coinciden (lo cual tiene sentido). ¿Alguien experimentó el mismo problema hasta ahora?

Hans Knöchel
fuente

Respuestas:

251

La declaración de bloque con paréntesis vacíos:

void (^)()

tiene la misma semántica que un puntero de función con paréntesis vacíos:

void (*)()

No significa que no haya argumentos. Significa que los argumentos no están especificados, por lo tanto, abre el camino a errores ya que puede llamarlo de las siguientes maneras:

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

Al declarar bloques sin parámetros, utilice siempre:

void (^)(void)

Apple no estaba haciendo eso correctamente en todas partes y probablemente no lo estén arreglando para las API antiguas por razones de compatibilidad. Tendrá que mantener esa advertencia allí hasta que cambie a la API más nueva.

También puede desactivar esa advertencia ( -Wstrict-prototypes): ingrese la descripción de la imagen aquí

o usando #pragma(gracias @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

Vea la discusión de LLVM aquí o el error en openradar .

Tenga en cuenta que no hubo cambios en el funcionamiento interno de las API, todo el código seguirá funcionando. Solo sabremos que la API no es tan buena como debería.

Sulthan
fuente
5
También puede usar pragmas para eliminar la advertencia al implementar la API de iOS: #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wstrict-prototypes" - (void) application: (UIApplication *) application handleActionWithIdentifier: (NSString *) identifier forRemoteNotification: (NSDictionary *) userInfo withResponseInfo: (NSDictionary *) responseInfo completacionHandler: (void (^) ()) completacionHandler {#pragma clang diagnóstico pop
davidisdk
1
Recibí alrededor de 20 advertencias de estos con la API de JBChartView. Es bueno poder apagarlos hasta que decidan actualizar para Swift 4.
Edison
7
@tymac Esta es una advertencia de objc. No tiene nada que ver con Swift.
Sulthan
> "Cuando declares bloques sin parámetros, usa siempre (void)" <¿Puedes agregar cómo debería verse en el código? Como alternativa a void (^)()orvoid (*)()
pkamb
2
@pkamb Cuando su bloque no toma ningún parámetro (es decir void(^)()), incluyen explícitamente voiden el paréntesis: void(^)(void).
Ben Stock