如何使 Swift 中的警告静音?
How to silence a warning in Swift?
我有一段代码生成了很多警告(已弃用 API)
使用 clang* 我可以做到:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
...
#pragma clang diagnostic pop
但是这在 Swift 中不起作用。
如何在Swift中完成?
注意:我不想全局禁用警告,甚至不想在整个文件范围内禁用警告,而只是在源代码的特定部分禁用特定警告。
我不想要条件编译(这是假设重复的建议答案)。
我只想在不使用新的 APIs.
的情况下使警告静音
截至 2021 年,Xcode 13.0,共识是无法实现。
如果 Apple 添加此功能,我会 update/edit 这个答案。
将它放入 WWDC 2022 的愿望清单中!
实际上,您 可以 通过在封闭的逻辑结构(即 function/type)中使用 @available
来抑制这些警告。
例如,假设您有一些使用 AddressBook 框架的代码,但您是针对 iOS 9.
构建的
@available(iOS, deprecated: 9.0)
func addressBookStatus() -> ABAuthorizationStatus {
return ABAddressBookGetAuthorizationStatus()
}
从 Xcode 7.0.1 开始,这将阻止显示内联警告。
在 Swift 中没有消除弃用警告的通用构造,但有一个可以在许多情况下应用的解决方法。
假设您在 class Foo
上有一个方法 getLatestImage()
,它使用已弃用的 methods/classes.
按照 Daniel Thorpe 的描述使用 @available
来消除 方法中的所有警告:
@available(iOS, deprecated: 9.0)
func getLatestImage() -> UIImage? {
...
}
现在您想 调用 方法 getLatestImage()
而没有弃用警告。您可以通过首先定义协议和扩展来实现:
private protocol GetLatestImage {
func getLatestImage() -> UIImage?
}
extension Foo: GetLatestImage {}
然后在没有弃用警告的情况下调用该方法。
如果foo
是Foo
的实例:
(foo as GetLatestImage).getLatestImage() // no deprecation warning
如果你想调用 Foo 的静态 property/function:
(Foo.self as GetLatestImage.Type).someStaticProperty
结果是您有 Swift 使用已弃用 API 的代码,没有任何弃用警告。
虽然目前无法消除 Swift 中的弃用警告,但从技术上讲,您可以通过编辑头文件为特定符号做到这一点。
- 复制已弃用的符号名称
- Select
File
> Open Quickly
粘贴符号并按Enter
确保“快速打开”框中的 Swift 图标已禁用
Select File
> Show in Finder
- 更改文件权限以允许在必要时进行编辑
- 编辑符号的弃用宏。请参阅周围的 API 以供参考。例如。替换:
__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_6, __MAC_10_10, __IPHONE_3_0, __IPHONE_8_0)
与
__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0)
现在有一个不那么令人分心的警告了,您无能为力。
我知道,它很脏。但是,如果当前 SDK 中没有可用的替代品API,它应该是安全的。一旦 Xcode 的新版本发布,更改将被覆盖,您将再次看到警告。然后您可以测试新的 SDK 和 OS 以确保已弃用的 API 仍然可用并且没有得到替代。
如果您能提出任何缺点,请发表评论。
我遇到了 class 或结构之外的顶级函数的问题:
@available(*, deprecated)
func GetImage(url: URL) -> UIImage? { ... }
我与 Apple 的一位工程师谈过,他们告诉我您可以通过协议隐藏实现并将扩展标记为已弃用。让我们看看它是如何工作的:
- 为要包装的函数创建一个具有相似签名的协议。
- 在扩展中的任何 class 或结构上使用协议。
- 将扩展标记为已弃用。
扩展中的所有内容都不会出现任何弃用警告。
protocol ImageStoreProtocol {
func imageFromURL(_ url: URL) -> UIImage?
}
class ImageStore {}
@available(*, deprecated)
extension ImageStore: ImageStoreProtocol {
func imageFromURL(_ url: URL) -> UIImage? {
return GetImage(url: url) // Warning does't show up
}
}
我有一段代码生成了很多警告(已弃用 API)
使用 clang* 我可以做到:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
...
#pragma clang diagnostic pop
但是这在 Swift 中不起作用。
如何在Swift中完成?
注意:我不想全局禁用警告,甚至不想在整个文件范围内禁用警告,而只是在源代码的特定部分禁用特定警告。
我不想要条件编译(这是假设重复的建议答案)。 我只想在不使用新的 APIs.
的情况下使警告静音截至 2021 年,Xcode 13.0,共识是无法实现。
如果 Apple 添加此功能,我会 update/edit 这个答案。
将它放入 WWDC 2022 的愿望清单中!
实际上,您 可以 通过在封闭的逻辑结构(即 function/type)中使用 @available
来抑制这些警告。
例如,假设您有一些使用 AddressBook 框架的代码,但您是针对 iOS 9.
构建的@available(iOS, deprecated: 9.0)
func addressBookStatus() -> ABAuthorizationStatus {
return ABAddressBookGetAuthorizationStatus()
}
从 Xcode 7.0.1 开始,这将阻止显示内联警告。
在 Swift 中没有消除弃用警告的通用构造,但有一个可以在许多情况下应用的解决方法。
假设您在 class Foo
上有一个方法 getLatestImage()
,它使用已弃用的 methods/classes.
按照 Daniel Thorpe 的描述使用 @available
来消除 方法中的所有警告:
@available(iOS, deprecated: 9.0)
func getLatestImage() -> UIImage? {
...
}
现在您想 调用 方法 getLatestImage()
而没有弃用警告。您可以通过首先定义协议和扩展来实现:
private protocol GetLatestImage {
func getLatestImage() -> UIImage?
}
extension Foo: GetLatestImage {}
然后在没有弃用警告的情况下调用该方法。
如果foo
是Foo
的实例:
(foo as GetLatestImage).getLatestImage() // no deprecation warning
如果你想调用 Foo 的静态 property/function:
(Foo.self as GetLatestImage.Type).someStaticProperty
结果是您有 Swift 使用已弃用 API 的代码,没有任何弃用警告。
虽然目前无法消除 Swift 中的弃用警告,但从技术上讲,您可以通过编辑头文件为特定符号做到这一点。
- 复制已弃用的符号名称
- Select
File
>Open Quickly
粘贴符号并按
Enter
确保“快速打开”框中的 Swift 图标已禁用
Select
File
>Show in Finder
- 更改文件权限以允许在必要时进行编辑
- 编辑符号的弃用宏。请参阅周围的 API 以供参考。例如。替换:
__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_6, __MAC_10_10, __IPHONE_3_0, __IPHONE_8_0)
与
__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_0)
现在有一个不那么令人分心的警告了,您无能为力。
我知道,它很脏。但是,如果当前 SDK 中没有可用的替代品API,它应该是安全的。一旦 Xcode 的新版本发布,更改将被覆盖,您将再次看到警告。然后您可以测试新的 SDK 和 OS 以确保已弃用的 API 仍然可用并且没有得到替代。
如果您能提出任何缺点,请发表评论。
我遇到了 class 或结构之外的顶级函数的问题:
@available(*, deprecated)
func GetImage(url: URL) -> UIImage? { ... }
我与 Apple 的一位工程师谈过,他们告诉我您可以通过协议隐藏实现并将扩展标记为已弃用。让我们看看它是如何工作的:
- 为要包装的函数创建一个具有相似签名的协议。
- 在扩展中的任何 class 或结构上使用协议。
- 将扩展标记为已弃用。
扩展中的所有内容都不会出现任何弃用警告。
protocol ImageStoreProtocol {
func imageFromURL(_ url: URL) -> UIImage?
}
class ImageStore {}
@available(*, deprecated)
extension ImageStore: ImageStoreProtocol {
func imageFromURL(_ url: URL) -> UIImage? {
return GetImage(url: url) // Warning does't show up
}
}