คำเตือน“ การประกาศฟังก์ชันนี้ไม่ใช่ต้นแบบ” ใน Xcode 9


119

เมื่อใช้ Xcode 9 This function declaration is not a prototypeมีบางคำเตือนคอมไพเลอร์กล่าวว่า แนะนำให้เพิ่มลงvoidในเนื้อความของวิธีการซึ่งจะแก้ไขได้ ปัญหาที่ฉันพบคือคำเตือนเหล่านั้นจะถูกส่งไปยัง system-API เช่นUIApplicationdelegate-method:

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

สิ่งนี้สามารถแก้ไขได้ดังต่อไปนี้:

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

ตอนนี้ฉันสงสัยว่าวิธีการมอบสิทธิ์จะยังคงใช้งานได้ในระยะยาวหรือ Apple จะแทรกvoidiOS 11 เวอร์ชันเบต้าในภายหลัง ฉันสงสัยเพราะถ้าฉันรวมvoidเนื้อหา Xcode จะบ่นเกี่ยวกับตัวเลือกวิธีการที่ไม่ตรงกัน (ซึ่งสมเหตุสมผล) มีใครประสบปัญหาเดียวกันหรือไม่

คำตอบ:


251

การประกาศบล็อกที่มีวงเล็บว่าง:

void (^)()

มีความหมายเช่นเดียวกับตัวชี้ฟังก์ชันที่มีวงเล็บว่าง:

void (*)()

ก็ไม่ได้หมายความว่าไม่มีข้อโต้แย้ง หมายความว่าไม่มีการระบุอาร์กิวเมนต์ดังนั้นจึงเปิดทางไปสู่จุดบกพร่องเนื่องจากคุณสามารถเรียกมันได้ด้วยวิธีต่อไปนี้:

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

เมื่อประกาศบล็อกโดยไม่มีพารามิเตอร์ให้ใช้:

void (^)(void)

Apple ไม่ได้ทำอย่างนั้นอย่างถูกต้องทุกที่และอาจไม่ได้แก้ไขสำหรับ API เก่าด้วยเหตุผลด้านความเข้ากัน คุณจะต้องเก็บคำเตือนนั้นไว้ที่นั่นจนกว่าจะย้ายไปใช้ API ที่ใหม่กว่า

คุณยังสามารถปิดคำเตือนนั้น ( -Wstrict-prototypes): ใส่คำอธิบายภาพที่นี่

หรือใช้#pragma(ขอบคุณ@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

ดูการอภิปราย LLVM ที่นี่หรือข้อผิดพลาดในopenradar

โปรดทราบว่าไม่มีการเปลี่ยนแปลงในการทำงานภายในของ API แต่โค้ดทั้งหมดจะยังใช้งานได้ เราจะรู้เพียงว่า API ไม่ดีเท่าที่ควร


5
คุณยังสามารถใช้ pragmas เพื่อลบคำเตือนเมื่อใช้ iOS API: #pragma clang diagnostic push #pragma clang การวินิจฉัยที่ละเว้นแอปพลิเคชัน "-Wstrict-prototypes" - (void): (UIApplication *) application handleActionWithIdentifier: (NSString *) ตัวระบุ forRemoteNotification: (NSDictionary *) userInfo withResponseInfo: (NSDictionary *) responseInfo completeHandler: (void (^) ())
completeHandler

1
มีคำเตือนประมาณ 20 รายการด้วย JBChartView API เป็นเรื่องดีที่สามารถปิดได้จนกว่าพวกเขาจะตัดสินใจอัปเดตสำหรับ Swift 4
Edison

7
@tymac นี่คือคำเตือน objc มันไม่มีอะไรเกี่ยวข้องกับ Swift
Sulthan

> "เมื่อประกาศบล็อกโดยไม่มีพารามิเตอร์ให้ใช้ (โมฆะ) เสมอ" <คุณสามารถเพิ่มสิ่งที่ควรมีในโค้ดได้หรือไม่? เป็นอีกทางเลือกหนึ่งvoid (^)()หรือvoid (*)()
pkamb

2
@pkamb เมื่อบล็อกของคุณไม่ได้ใช้พารามิเตอร์ใด ๆ (เช่นvoid(^)()) อย่างชัดเจนรวมถึงในวงเล็บ:void void(^)(void)
Ben Stock
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.