Swift替代 #pragma clang diagnostic

17

问题

最近我在一个第三方工具(WEPopover)的这段代码中遇到了一个警告:

_effectivePopoverContentSize = _contentViewController.contentSizeForViewInPopover;

这会产生以下警告:

warning: 'contentSizeForViewInPopover' is deprecated: first deprecated in iOS 7.0 - Use UIViewController.preferredContentSize instead. [-Wdeprecated-declarations]
            _effectivePopoverContentSize = _contentViewController.contentSizeForViewInPopover;

在Objective-C中,解决这个问题的一种临时方法是使用pragma clang diagnostic来消除错误(我会让代码作者处理真正的修复)。因此,我将代码修改如下:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
            _effectivePopoverContentSize = _contentViewController.contentSizeForViewInPopover;

#pragma clang diagnostic pop

问题

这段代码可以正常工作,但这让我考虑如果在编写Swift时需要消除类似的误报警告,是否存在任何替代方案?

考虑因素

我已经观察到,我可以在整个项目中停用此类警告(使用Xcode设置),但我想考虑上述内联问题。我还考虑在我的Swift项目中的.bridging-header.h文件中添加#define,并以某种方式利用它; 但是,我正在寻找解决此问题的特定于Swift的解决方案。我确实了解pragma不再可用,并且我已经搜索了SO并找到了类似但不重复的问题。

更新的解决方案:Swift 2.0

提供的答案处理了我对内联警告的担忧。可用性命令应该允许完全避免此类问题,因为在编译时会发出警告。

苹果的Swift书明确说明:

“您在if或guard语句中使用可用性条件来有条件地执行一块代码,具体取决于您要使用的API在运行时是否可用。编译器在验证该“代码块中的API是否可用时使用可用性条件中的信息。

 if #available(iOS 9, OSX 10.10, *) {
 // Use iOS 9 APIs on iOS, and use OS X v10.10 APIs on OS X 
 } else {
 // Fall back to earlier iOS and OS X APIs 
 }

有人甚至可以使用guard语句和可用性结合,除非满足可用条件,否则提前退出范围。

guard #available(iOS 8.0, OSX 10.10, *) else { return }

此外,我对处理宏的相关问题进行了如下说明。请记住,Swift没有预处理器,这些工具似乎是可行的选择。
“简单宏”
在C和Objective-C中,您通常使用#define指令来定义原始常量,而在Swift中,则使用全局常量。例如,常量定义#define FADE_ANIMATION_DURATION 0.35可以用let FADE_ANIMATION_DURATION = 0.35更好地表达出来。因为类似常量的简单宏直接映射到Swift全局变量,编译器自动导入在C和Objective-C源文件中定义的简单宏。
“复杂宏”
复杂宏在C和Objective-C中使用,但在Swift中没有对应物。复杂宏是不定义常量的宏,包括带括号的函数样式宏。您在C和Objective-C中使用复杂宏以避免类型检查约束或避免重新输入大量样板代码。然而,宏可能会使调试和重构困难。在Swift中,您可以使用函数和泛型来实现相同的结果,而不需要进行任何妥协。因此,“在C和Objective-C源文件中的复杂宏不可用于Swift代码。”
摘自:Apple Inc. “使用Swift与Cocoa和Objective-C(Swift 2预发布版)。”iBooks. https://itun.es/us/utTW7.l API的开发者可以使用以下方式标记Swift中函数的可用性:
available(iOS 8.0, OSX 10.10, *)
func useShinyNewFeature() {
    // ...
}

摘自:苹果公司。“使用Swift与Cocoa和Objective-C(Swift 2预发布版)。”iBooks. https://itun.es/us/utTW7.l

为Swift重写的函数添加这些标记似乎是保持框架向后兼容性的好方法。guard / available组合将允许那些框架的用户根据需要调整逻辑。这让我放心处理内联警告,API回退和宏等问题。


你可以考虑为第三方工具使用单独的框架目标,并为该目标指定适当的构建设置。然后在你的主项目中,你可以保留适合你代码的构建设置。 - Rob
1
对于那些经过此处的人,有一些特定的信息...截至2015年5月13日,Swift不支持预处理器宏。来自《使用Swift与Cocoa和Objective-C》(第Interoperability章,Preprocessor Directives节)“Swift编译器不包括预处理器。相反,它利用编译时属性、构建配置和语言特性来实现相同的功能。因此,在Swift中不导入预处理器指令。”看起来Swift永远不会支持clang诊断宏,目前也没有内置的本地替代方案。 - Blake Merryman
@BlakeMerryman,我建议你将评论中的信息添加为答案,并通知提问者以便他能接受它。这样就不会再显示为未回答了。祝好! - phlebotinum
@robo,我最终重新调整了我的答案,并结合了Swift 2的新信息(以及我自己对Swift的改进经验)。感谢你的提醒。希望我的答案已经足够了。 - Blake Merryman
这个回答解决了你的问题吗? [如何在Swift中消除警告?] (https://dev59.com/OlwZ5IYBdhLWcg3wWvVY) - Top-Master
1个回答

2
截至目前为止,Swift 2.0版本(本文写作时仍处于beta测试阶段)仍未包含预处理器,并且这种情况看起来在短时间内不会改变(如果有的话)。预处理器所提供的有益功能已经以各种方式内置于语言中(本文不会涵盖所有内容,请参阅文档),并且是编译时级别功能。
有两个功能我想提一下(一个旧的,一个新的),这可能是你正在寻找的:
1.条件编译 - 如《使用Swift与Cocoa和Objective-C》所述,您可以实现条件编译语句,这样您就可以只在特定操作系统或处理器体系结构下编译代码。它看起来像这样:
``` #if os(iOS) // iOS #elseif os(OSX) // OSX #elseif os(tvOS) // tvOS #else // Linux? #endif ```
2.API可用性检查 - 如《Swift编程语言》所述,现在可以根据平台和操作系统版本检查API的可用性。这将使您能够利用更新的API,同时允许您处理该功能在旧(或不同)平台或操作系统上不可用的情况。您可以使用这个来替换备用实现或向用户呈现解释。它看起来像这样:
``` if #available(iOS 9, OSX 10.10, *) { // Use iOS 9 APIs on iOS, and use OS X v10.10 APIs on OS X } else { // Fall back to earlier iOS and OS X APIs } ```
这些工具(以及许多其他内置于语言中的工具)应该允许开发人员替换Objective-C和C预处理器宏。个人认为它们是一个巨大的改进。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接