不建议在Swift 4模式下使用Swift 3 @objc推论吗?
本文翻译自:The use of Swift 3 @objc inference in Swift 4 mode is deprecated?
Briefly, while using Xcode 9 Beta, I have run into the following warning: 简要地说,在使用Xcode 9 Beta时,我遇到了以下警告:
The use of Swift 3 @objc inference in Swift 4 mode is deprecated. 不建议在Swift 4模式下使用Swift 3 @objc推断。 Please address deprecated @objc inference warnings, test your code with “Use of deprecated Swift 3 @objc inference” logging enabled, and disable Swift 3 @objc inference.** 请解决已弃用的@objc推断警告,启用“使用已弃用的Swift 3 @objc推断”日志记录来测试您的代码,并禁用Swift 3 @objc推断。**
After some research, I still have no idea how to fix the issue. 经过研究,我仍然不知道如何解决该问题。 I would greatly appreciate any tips on how to fix this issue as well as an explanation of what is going on. 我将不胜感激有关如何解决此问题的所有技巧以及对所发生情况的解释。
My goal is to grasp a better understanding of what is happening with my code. 我的目标是更好地理解我的代码正在发生的事情。
#1楼
参考:https://stackoom.com/question/30D5w/不建议在Swift-模式下使用Swift-objc推论吗
#2楼
I got rid of this warning by changing the "Swift 3 @objc Inference" build setting of my targets to "Default". 通过将目标的“ Swift 3 @objc Inference”构建设置更改为“ Default”,我摆脱了此警告。
From this article : 从这篇文章 :
Before Swift 4, the compiler made some Swift declarations automatically available to Objective-C . 在Swift 4之前,编译器自动将一些Swift声明提供给Objective-C 。 For example, if one subclassed from NSObject, the compiler created Objective-C entry points for all methods in such classes. 例如,如果从NSObject继承了一个子类,则编译器会为此类中的所有方法创建Objective-C入口点。 The mechanism is called @objc inference. 该机制称为@objc推断。
In Swift 4, such automatic @objc inference is deprecated because it is costly to generate all those Objective-C entry points. 在Swift 4中,不建议使用这种自动@objc推断,因为生成所有这些Objective-C入口点的成本很高 。 When "Swift 3 @objc Inference" setting is set to "On", it allows the old code to work. 当“ Swift 3 @objc Inference”设置设置为“ On”时,它将允许旧代码起作用。 However, it will show deprecation warnings that need to be addressed. 但是,它将显示需要解决的弃用警告。 It is recommended to "fix" these warnings and switch the setting to "Default" , which is the default for new Swift projects. 建议“修复”这些警告并将设置切换为“默认” ,这是新Swift项目的默认设置。
Please also refer to this Swift proposal for more information. 另请参阅此Swift提案 。
#3楼
Migrator cannot identify all the functions that need @objc Inferred Objective-C thunks marked as deprecated to help you find them 迁移器无法识别所有需要@objc的功能推断为不推荐使用的 Objective-C类可以帮助您找到它们
• Build warnings about deprecated methods •建立有关不赞成使用的方法的警告
• Console messages when running deprecated thunks •运行已弃用的thunk时的控制台消息
#4楼
You can simply pass to "default" instead of "ON". 您可以简单地传递给“默认”而不是“开”。 Seems more adherent to Apple logic. 似乎更遵守Apple的逻辑。
(but all the other comments about the use of @obj
remains valid.) (但有关使用@obj
所有其他注释仍然有效。)
#5楼
- What is @objc
inference? - @objc
推论是什么? What is going on? 到底是怎么回事?
In Swift 3
, the compiler infers @objc
in a number of places so you wouldn't have to. 在Swift 3
,编译器@objc
在许多地方推断@objc
,因此您不必这样做。 In other words, it makes sure to add @objc
for you! 换句话说,它确保为您添加@objc
!
In Swift 4
, the compiler no longer does this (as much). 在Swift 4
,编译器不再这样做(尽可能多)。 You now must add @objc
explicitly. 现在,您必须显式添加@objc
。
By default, if you have a pre-Swift 4 project, you will get warnings about this. 默认情况下,如果您有一个Swift 4之前的项目,则会收到有关此问题的警告。 In a Swift 4 project, you will get build errors. 在Swift 4项目中,您将获得构建错误。 This is controlled via the SWIFT_SWIFT3_OBJC_INFERENCE
build setting. 这是通过SWIFT_SWIFT3_OBJC_INFERENCE
构建设置控制的。 In a pre-Swift 4 project this is set to On
. 在Swift 4之前的项目中,将其设置为On
。 I would recommend to set this to Default
(or Off
), which is now the default option on a new project. 我建议将其设置为Default
(或Off
),这是新项目的默认选项。
It will take some time to convert everything, but since it's the default for Swift 4, it's worth doing it. 转换所有内容将花费一些时间,但是由于它是Swift 4的默认设置,因此值得这么做。
- How do I stop the compiler warnings/errors? -如何停止编译器警告/错误?
There are two ways to go about converting your code so the compiler doesn't complain. 有两种方法可以转换代码,以使编译器不会抱怨。
One is to use @objc
on each function or variable that needs to be exposed to the Objective-C runtime: 一种是在需要公开给Objective-C运行时的每个函数或变量上使用@objc
:
@objc func foo() {
}
The other is to use @objcMembers
by a Class
declaration. 另一种是通过Class
声明使用@objcMembers
。 This makes sure to automatically add @objc
to ALL the functions and variables in the class. 这样可以确保将@objc
自动添加到类中的所有函数和变量中。 This is the easy way, but it has a cost, for example, it can increase the size of your application by exposing functions that did not need to be exposed. 这是简单的方法,但是有一定的成本,例如,它可以通过公开不需要公开的功能来增加应用程序的大小。
@objcMembers class Test {
}
- What is @objc
and why is it necessary? - @objc
是什么,为什么有必要?
If you introduce new methods or variables to a Swift class, marking them as @objc
exposes them to the Objective-C runtime. 如果您向Swift类引入新的方法或变量, @objc
其标记为@objc
它们公开给Objective-C运行时。 This is necessary when you have Objective-C code that uses your Swift class, or, if you are using Objective-C-type features like Selectors
. 如果您拥有使用Swift类的Objective-C代码,或者使用的是Selectors
类的Objective-C类型的功能,则这是必需的。 For example, the target-action pattern: button.addTarget(self, action:#selector(didPressButton), for:.touchUpInside)
例如,目标动作模式: button.addTarget(self, action:#selector(didPressButton), for:.touchUpInside)
- Why would I not mark everything @objc
? -为什么我不标记所有@objc
?
There are negatives that come with marking something as @objc
: 将东西标记为@objc
会带来负面@objc
:
- Increased application binary size 应用程序二进制文件大小增加
- No function overloading 没有功能重载
Please keep in mind that this is a very high-level summary and that it is more complicated than I wrote. 请记住,这是一个非常高级的摘要,它比我写的还要复杂。 I would recommend reading the actual proposal for more information. 我建议阅读实际的建议以获取更多信息。
Sources: 资料来源:
- https://github.com/apple/swift-evolution/blob/master/proposals/0160-objc-inference.md https://github.com/apple/swift-evolution/blob/master/proposals/0160-objc-inference.md
- https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/WritingSwiftClassesWithObjective-CBehavior.html#//apple_ref/doc/uid/TP40014216-CH5-ID86 https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/WritingSwiftClassesWithObjective-CBehavior.html#//apple_ref/doc/uid/TP40014216-CH5-ID86
#6楼
Indeed, you'll get rid of those warnings by disabling Swift 3 @objc Inference. 确实,通过禁用Swift 3 @objc Inference可以消除这些警告。 However, subtle issues may pop up. 但是,细微的问题可能会弹出。 For example, KVO will stop working. 例如,KVO将停止工作。 This code worked perfectly under Swift 3: 这段代码在Swift 3下完美运行:
for (key, value) in jsonDict {
if self.value(forKey: key) != nil {
self.setValue(value, forKey: key)
}
}
After migrating to Swift 4, and setting "Swift 3 @objc Inference" to default, certain features of my project stopped working . 迁移到Swift 4并将“ Swift 3 @objc Inference”设置为默认值后, 我项目的某些功能停止工作 。 It took me some debugging and research to find a solution for this. 我花了一些调试和研究才能找到解决方案。 According to my best knowledge, here are the options: 据我所知,以下是选项:
- Enable "Swift 3 @objc Inference" (only works if you migrated an existing project from Swift 3) 启用“ Swift 3 @objc Inference”(仅当您从Swift 3迁移现有项目时才有效)
- Mark the affected methods and properties as @objc 将受影响的方法和属性标记为@objc
- Re-enable ObjC inference for the entire class using @objcMembers 使用@objcMembers为整个类重新启用ObjC推断
Re-enabling @objc inference leaves you with the warnings, but it's the quickest solution. 重新启用@objc推断会给您警告,但这是最快的解决方案。 Note that it's only available for projects migrated from an earlier Swift version. 请注意,它仅适用于从早期Swift版本迁移的项目。 The other two options are more tedious and require some code-digging and extensive testing. 其他两个选项比较繁琐,需要进行一些代码挖掘和大量测试。
See also https://github.com/apple/swift-evolution/blob/master/proposals/0160-objc-inference.md 另请参见https://github.com/apple/swift-evolution/blob/master/proposals/0160-objc-inference.md