Die Warnung "Diese Funktionsdeklaration ist kein Prototyp" in Xcode 9

119

Bei Verwendung von Xcode 9 werden einige Compiler-Warnungen angezeigt This function declaration is not a prototype. Es wird vorgeschlagen void, den Methodenkörper zu erweitern, um ihn aufzulösen. Das Problem, das ich habe, ist, dass diese Warnungen auch für System-APIs wie UIApplicationDelegate-Methoden ausgegeben werden:

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

Dies könnte durch Folgendes gelöst werden:

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

Jetzt frage ich mich, ob die Delegate-Methoden langfristig noch funktionieren oder Apple die voidin späteren iOS 11 Beta-Versionen einfügt. Ich bin neugierig, denn wenn ich den voidKörper einbeziehe, beschwert sich Xcode über nicht übereinstimmende Methodenselektoren (was Sinn macht). Hat jemand das gleiche Problem bisher erlebt?

Hans Knöchel
quelle

Antworten:

251

Die Blockdeklaration mit leerer Klammer:

void (^)()

hat die gleiche Semantik wie ein Funktionszeiger mit leerer Klammer:

void (*)()

Dies bedeutet nicht, dass es keine Argumente gibt. Dies bedeutet, dass die Argumente nicht angegeben werden. Daher wird der Weg für Fehler geöffnet, da Sie sie auf folgende Arten aufrufen können:

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

Wenn Sie Blöcke ohne Parameter deklarieren, verwenden Sie immer:

void (^)(void)

Apple hat das nicht überall richtig gemacht und das wird aus Kompatibilitätsgründen wahrscheinlich nicht für alte APIs behoben. Sie müssen diese Warnung dort aufbewahren, bis Sie zur neueren API wechseln.

Sie können diese Warnung auch deaktivieren ( -Wstrict-prototypes): Geben Sie hier die Bildbeschreibung ein

oder mit #pragma(danke @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

Siehe die LLVM-Diskussion hier oder den Fehler auf openradar .

Beachten Sie, dass sich an der internen Funktionsweise der APIs nichts geändert hat. Der gesamte Code funktioniert weiterhin. Wir werden nur wissen, dass die API nicht so gut ist, wie sie sein sollte.

Sulthan
quelle
5
Sie können auch Pragmas verwenden, um die Warnung bei der Implementierung der iOS-API zu entfernen: #pragma clang diagnostischer Push #pragma clang Diagnose ignoriert "-Wrikte Prototypen" - (nichtige) Anwendung: (UIApplication *) AnwendungshandleActionWithIdentifier: (NSString *) Kennung für RemoteNotification: (NSDictionary *) userInfo withResponseInfo: (NSDictionary *) responseInfo CompletionHandler: (void (^) ()) CompletionHandler {#pragma Clang Diagnostic Pop
Davidisdk
1
Mit der JBChartView-API wurden ungefähr 20 Warnungen angezeigt. Es ist schön, sie ausschalten zu können, bis sie sich für ein Update für Swift 4 entscheiden.
Edison
7
@tymac Dies ist eine objc Warnung. Es hat nichts mit Swift zu tun.
Sulthan
> "Wenn Sie Blöcke ohne Parameter deklarieren, verwenden Sie immer (void)" <Können Sie hinzufügen, wie das im Code aussehen soll? Als Alternative zu void (^)()orvoid (*)()
pkamb
2
@pkamb Wenn Ihr Block keine Parameter (dh void(^)()) akzeptiert, fügen Sie dies explizit voidin die Klammern ein : void(^)(void).
Ben Stock