Cảnh báo “Khai báo hàm này không phải là nguyên mẫu” trong Xcode 9


119

Khi sử dụng Xcode 9, có một số cảnh báo trình biên dịch nói rằng This function declaration is not a prototype. Nó gợi ý thêm voidvào phần thân phương thức, nó sẽ giải quyết nó. Vấn đề tôi đang gặp phải là những cảnh báo đó cũng được gửi cho UIApplicationcác phương thức ủy quyền của API hệ thống :

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

Điều này có thể được giải quyết bằng cách sau:

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

Bây giờ tôi đang tự hỏi liệu các phương pháp ủy quyền sẽ vẫn hoạt động lâu dài hay Apple sẽ chèn các voidphiên bản iOS 11 Beta sau này. Tôi tò mò vì nếu tôi bao gồm phần voidthân, Xcode sẽ phàn nàn về các bộ chọn phương pháp không khớp (điều này có ý nghĩa). Có ai đó đã gặp vấn đề tương tự cho đến nay?

Câu trả lời:


251

Khai báo khối với dấu ngoặc trống:

void (^)()

có cùng ngữ nghĩa như một con trỏ hàm có dấu ngoặc đơn trống:

void (*)()

Nó không có nghĩa là không có tranh luận. Nó có nghĩa là các đối số không được chỉ định, do đó nó mở đường cho lỗi vì bạn có thể gọi nó theo những cách sau:

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

Khi khai báo các khối không có tham số, hãy luôn sử dụng:

void (^)(void)

Apple đã không làm điều đó một cách chính xác ở mọi nơi và họ có thể không sửa lỗi đó cho các API cũ vì lý do tương thích. Bạn sẽ phải giữ cảnh báo đó ở đó cho đến khi chuyển sang API mới hơn.

Bạn cũng có thể tắt cảnh báo đó ( -Wstrict-prototypes): nhập mô tả hình ảnh ở đây

hoặc sử dụng #pragma(cảm ơn @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

Xem thảo luận LLVM tại đây hoặc lỗi trên openradar .

Lưu ý rằng không có thay đổi nào trong hoạt động nội bộ của các API, tất cả mã sẽ vẫn hoạt động. Chúng tôi sẽ chỉ biết rằng API không tốt như mong muốn.


5
Bạn cũng có thể sử dụng pragmas để xóa cảnh báo khi triển khai API iOS: #pragma clang chẩn đoán đẩy #pragma clang chẩn đoán bị bỏ qua "-Wstrict-prototypes" - (void) ứng dụng: (UIApplication *) ứng dụng handleActionWithIdentifier: (NSString *) định danh choRemoteNotification: (NSDictionary *) UserInfo withResponseInfo: (NSDictionary *) responseInfo completionHandler: (void (^) ()) {completionHandler #pragma kêu vang chẩn đoán pop
davidisdk

1
Nhận được khoảng 20 cảnh báo trong số này với API JBChartView. Nó thoải mái để có thể tắt chúng cho đến khi họ quyết định cập nhật cho Swift 4.
Edison

7
@tymac Đây là cảnh báo phản đối. Nó không liên quan gì đến Swift.
Sulthan

> "Khi khai báo các khối không có tham số, luôn sử dụng (void)" <Bạn có thể thêm những gì sẽ trông như thế nào trong mã không? Để thay thế cho void (^)()hoặcvoid (*)()
pkamb

2
@pkamb Khi khối bạn không mất bất kỳ thông số (ví dụ void(^)()), rõ ràng bao gồm voidtrong ngoặc đơn: void(^)(void).
Ben Stock
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.