Ostrzeżenie „Ta deklaracja funkcji nie jest prototypem” w Xcode 9

119

Podczas korzystania z Xcode 9 pojawiają się ostrzeżenia kompilatora This function declaration is not a prototype. Sugeruje dodanie voiddo treści metody, która rozwiąże problem. Problem, który mam, polega na tym, że te ostrzeżenia są również generowane dla UIApplicationmetod interfejsu API systemu, takich jak metody delegatów:

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

Można to rozwiązać w następujący sposób:

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

Teraz zastanawiam się, czy metody delegowania będą nadal działać na dłuższą metę, czy Apple wstawi voidw późniejszych wersjach iOS 11 Beta. Jestem ciekawy, ponieważ jeśli voiddołączę body, Xcode będzie narzekał na niedopasowanie selektorów metod (co ma sens). Czy ktoś do tej pory miał ten sam problem?

Hans Knöchel
źródło

Odpowiedzi:

251

Deklaracja bloku z pustym nawiasem:

void (^)()

ma taką samą semantykę jak wskaźnik funkcji z pustym nawiasem:

void (*)()

Nie oznacza to, że nie ma argumentów. Oznacza to, że argumenty nie są określone, dlatego otwiera drogę do błędów, ponieważ można to wywołać w następujący sposób:

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

Deklarując bloki bez parametrów, zawsze używaj:

void (^)(void)

Apple nie wszędzie robił to poprawnie i prawdopodobnie nie naprawiają tego w przypadku starych interfejsów API ze względu na kompatybilność. Będziesz musiał zachować to ostrzeżenie, dopóki nie przejdziesz na nowszy interfejs API.

Możesz również wyłączyć to ostrzeżenie ( -Wstrict-prototypes): wprowadź opis obrazu tutaj

lub używając #pragma(dzięki @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

Zobacz dyskusję LLVM tutaj lub błąd w openradar .

Zauważ, że nie było zmian w wewnętrznym działaniu API, cały kod będzie nadal działał. Będziemy tylko wiedzieć, że API nie jest tak dobre, jak powinno.

Sulthan
źródło
5
Możesz również użyć pragm, aby usunąć ostrzeżenie podczas implementacji interfejsu API iOS: #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wstrict-prototypes" - (void) application: (UIApplication *) application handleActionWithIdentifier: (NSString *) identyfikator forRemoteNotification: (NSDictionary *) userInfo withResponseInfo: (NSDictionary *) responseInfo completeHandler: (void (^) ())
completeHandler
1
Otrzymałem około 20 ostrzeżeń z tego powodu dzięki interfejsowi API JBChartView. Fajnie jest móc je wyłączyć, dopóki nie zdecydują się na aktualizację do Swift 4.
Edison
7
@tymac To jest ostrzeżenie objc. Nie ma to nic wspólnego z Swiftem.
Sulthan
> „Deklarując bloki bez parametrów, zawsze używaj (void)” <Czy możesz dodać, jak to powinno wyglądać w kodzie? Jako alternatywa dla void (^)()orvoid (*)()
pkamb
2
@pkamb Gdy blok nie bierze żadnych parametrów (tj void(^)()), wyraźnie zawierać voidw nawiasach: void(^)(void).
Ben Stock