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:

The use of Swift 3 @objc inference in Swift 4 mode is deprecated. 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.**

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.


Solution 1:

I got rid of this warning by changing the "Swift 3 @objc Inference" build setting of my targets to "Default".

Disable Swift 3 @objc inference in Xcode9

From this article:

Before Swift 4, the compiler made some Swift declarations automatically available to Objective-C. For example, if one subclassed from NSObject, the compiler created Objective-C entry points for all methods in such classes. The mechanism is called @objc inference.

In Swift 4, such automatic @objc inference is deprecated because it is costly to generate all those Objective-C entry points. When "Swift 3 @objc Inference" setting is set to "On", it allows the old code to work. 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.

Please also refer to this Swift proposal for more information.

Solution 2:

- What is @objc inference? What is going on?

In Swift 3, the compiler infers @objc in a number of places so you wouldn't have to. In other words, it makes sure to add @objc for you!

In Swift 4, the compiler no longer does this (as much). You now must add @objc explicitly.

By default, if you have a pre-Swift 4 project, you will get warnings about this. In a Swift 4 project, you will get build errors. This is controlled via the SWIFT_SWIFT3_OBJC_INFERENCE build setting. In a pre-Swift 4 project this is set to On. I would recommend to set this to Default (or Off), which is now the default option on a new project.

It will take some time to convert everything, but since it's the default for Swift 4, it's worth doing it.

- 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:

@objc func foo() {

}

The other is to use @objcMembers by a Class declaration. This makes sure to automatically add @objc to ALL the functions and variables in the class. 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?

If you introduce new methods or variables to a Swift class, marking them as @objc exposes them to the Objective-C runtime. 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. For example, the target-action pattern: button.addTarget(self, action:#selector(didPressButton), for:.touchUpInside)

- Why would I not mark everything @objc?

There are negatives that come with marking something as @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://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/WritingSwiftClassesWithObjective-CBehavior.html#//apple_ref/doc/uid/TP40014216-CH5-ID86

Solution 3:

Migrator cannot identify all the functions that need @objc Inferred Objective-C thunks marked as deprecated to help you find them
• Build warnings about deprecated methods
• Console messages when running deprecated thunks

enter image description here

Solution 4:

I had this warning with "Swift 3 @objc Inference" = "Default" setting. Then I realized that is was set for the Project - not for the target. So, make sure that you have "Default" setting in your target to get rid of the warning.

Solution 5:

You can simply pass to "default" instead of "ON". Seems more adherent to Apple logic.

(but all the other comments about the use of @obj remains valid.)