Peringatan “Deklarasi fungsi ini bukan prototipe” di Xcode 9

119

Saat menggunakan Xcode 9, ada beberapa peringatan compiler yang mengatakan This function declaration is not a prototype. Ia menyarankan untuk menambah voidtubuh metode, yang akan menyelesaikannya. Masalah yang saya alami adalah bahwa peringatan tersebut juga dilemparkan untuk sistem-API seperti UIApplicationmetode delegasi:

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

Ini dapat diselesaikan dengan cara berikut:

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

Sekarang saya bertanya-tanya apakah metode delegasi akan tetap berfungsi dalam jangka panjang atau Apple akan memasukkan voiddi versi iOS 11 Beta nanti. Saya penasaran karena jika saya menyertakan voidtubuh, Xcode akan mengeluh tentang pemilihan metode yang tidak cocok (yang masuk akal). Apakah seseorang mengalami masalah yang sama sejauh ini?

Hans Knöchel
sumber

Jawaban:

251

Deklarasi blok dengan tanda kurung kosong:

void (^)()

memiliki semantik yang sama dengan penunjuk fungsi dengan tanda kurung kosong:

void (*)()

Ini tidak berarti bahwa tidak ada argumen. Artinya argumen tidak ditentukan, oleh karena itu membuka jalan bagi bug karena Anda dapat memanggilnya dengan cara berikut:

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

Saat mendeklarasikan blok tanpa parameter, selalu gunakan:

void (^)(void)

Apple tidak melakukannya dengan benar di mana-mana dan mereka mungkin tidak memperbaikinya untuk API lama karena alasan kompatibilitas. Anda harus menyimpan peringatan itu di sana sampai Anda pindah ke API yang lebih baru.

Anda juga bisa mematikan peringatan itu ( -Wstrict-prototypes): masukkan deskripsi gambar di sini

atau menggunakan #pragma(terima kasih @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

Lihat pembahasan LLVM di sini atau bug di openradar .

Perhatikan bahwa tidak ada perubahan dalam kerja internal API, semua kode akan tetap berfungsi. Kami hanya akan tahu bahwa API tidak sebaik yang seharusnya.

Sulthan
sumber
5
Anda juga dapat menggunakan pragma untuk menghapus peringatan saat mengimplementasikan API iOS: #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wstrict-prototypes" - (void) application: (UIApplication *) application handleActionWithIdentifier: (NSString *) pengenal untukRemoteNotification: (NSDictionary *) userInfo withResponseInfo: (NSDictionary *) responseInfo completeHandler: (void (^) ())
completeHandler
1
Dapatkan sekitar 20 peringatan tentang ini dengan JBChartView API. Senang rasanya bisa mematikannya sampai mereka memutuskan untuk memperbarui Swift 4.
Edison
7
@tyas Ini adalah peringatan objc. Ini tidak ada hubungannya dengan Swift.
Sulthan
> "Saat mendeklarasikan blok tanpa parameter, selalu gunakan (void)" <Bisakah Anda menambahkan seperti apa tampilannya dalam kode? Sebagai alternatif dari void (^)()orvoid (*)()
pkamb
2
@pkamb Ketika blok Anda tidak mengambil parameter (yaitu void(^)()), secara eksplisit termasuk voiddalam kurung: void(^)(void).
Ben Stock