Xcode 9 中的“此函数声明不是原型”警告

Posted

技术标签:

【中文标题】Xcode 9 中的“此函数声明不是原型”警告【英文标题】:"This function declaration is not a prototype" warning in Xcode 9 【发布时间】:2017-11-12 09:04:12 【问题描述】:

使用 Xcode 9 时,有一些编译器警告说 This function declaration is not a prototype。它建议将void 添加到方法体中,这将解决它。我遇到的问题是,这些警告也会针对UIApplicationdelegate-methods 之类的系统 API 引发:

- (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 会在以后的 ios 11 Beta 版本中插入void。我很好奇,因为如果我包含 void 正文,Xcode 会抱怨方法选择器不匹配(这是有道理的)。到目前为止,有人遇到过同样的问题吗?

【问题讨论】:

【参考方案1】:

带空括号的块声明:

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 讨论 here 或 openradar 上的错误。

请注意,API 的内部工作没有变化,所有代码仍然可以工作。我们只会知道 API 没有达到应有的水平。

【讨论】:

您也可以在实现 iOS API 时使用 pragma 删除警告:#pragma clang diagnostic push #pragma clang diagnostic ignored "-Wstrict-prototypes" - (void)application:(UIApplication *)application handleActionWithIdentifier :(NSString *)RemoteNotification 标识符:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler #pragma clang diagnostic pop 使用 JBChartView API 收到了大约 20 个警告。在他们决定为 Swift 4 更新之前能够关闭它们真是太好了。 @tymac 这是一个 objc 警告。它与 Swift 无关。 > "当声明没有参数的块时,总是使用 (void)" void (^)() 或void (*)() 的替代品 @pkamb 当你的块不带任何参数时(即void(^)()),在括号中明确包含voidvoid(^)(void)

以上是关于Xcode 9 中的“此函数声明不是原型”警告的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 9.2 中的“警告:无法为签名者构建自签名根的链”警告

Xcode 9 的 Create Bot.. 窗口中的黄色警告三角形

Xcode 中的 iOS 9 警告 - 此文件设置为为比项目部署更早的版本构建。功能可能受到限制

Xcode 9.3 上的 Cocoapods 警告

Xcode 9.0.1 及更高版本的 100 多个“在 MapKit 和 VectorKit 中实现的类”警告

xcode8 iOS函数返回值使用警告