The use of Swift 3 @objc inference in Swift 4 mode is deprecated?
Asked Answered
W

12

496

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.

Whose answered 5/6, 2017 at 23:49 Comment(1)
I don't really get from warning message which object is causing it. Xcode simply doesn't say in which line that object is. Any advices how to find out where this warning is coming from?Burkhart
B
821

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.

Buttress answered 6/6, 2017 at 3:21 Comment(11)
Thank you Evgenii. Is this a long term Solution?Whose
@Whose yes, I believe so. According to the Swift proposal I mentioned in my answer, the objc inference is deprecated. The setting "Swift 3 objc Inference" is only present in the projects that were migrated from older versions of Swift. If one creates a new project, the setting is no longer present, which means that objc inference is off. It is recommended to address any objc inference warnings and set it to "Off".Buttress
The info message in XCode suggests that: "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." Any idea where to enable the said Swift 3 @objc inference logging?Moiramoirai
@courteouselk, according to the Swift proposal, one can set SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT environmental variable to values from 1 to 3 to see the usages of the Objective-C entry points in the logs.Buttress
Just put it to "Default" it's better than just turn it off.Augsburg
Just to add - You need to do this for all the build tagets, not just the project.Waldenburg
So we should try and avoid/find an alternative to any Swift 3 code that uses Objective-C like selectors?Hembree
Agree with @pierre23, you can (should?) use 'Default' rather than 'Off' - in fact 'Default' is now what the released version of Xcode 9 recommends in the warning.Carnet
What if the @objc tag is inside some framework/library that is in my project? Is there a way to turn those off? I couldn't find a way so far and I'm trying to turn on treat warnings as errors! ;)Valle
@Buttress Even after setting default still getting same warningUnknowable
I love a comprehensive explanation and clear to follow instruction. This does the job. Note, you may need to clear your build to get this warning to go away (i.e. Product > Clean). Also, you may need to repeat this procedure for <myProject>Tests as well... i.e. any other TARGETS in the project.Cockloft
O
272

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

Offering answered 3/8, 2017 at 18:6 Comment(5)
@objc does not imply dynamic dispatch, Swift is free to use static or virtual dispatch (and possibly execute different code as a result). The dynamic keyword is required to force Swift to use dynamic dispatch.Factotum
Are there other ways to add action to button? If @objc depricated what we must use?Trophic
In a mixed codebase with lots of Objective-C AND Swift, migrating to Swift 4 means adding dozens or hundreds of "@objc". Or am I doing something wrong? Seems wise to leave such a project at Swift 3 for the moment.Pretorius
@Pretorius yes, there may be quite a bit to convert. Split it up into stages. Leave SWIFT_SWIFT3_OBJC_INFERENCE at On. Convert to Swift 4. Then tackle the @objc stuff. To make it simple, follow basic rules: IF the Swift class is used in Objc-C code (via bridging header), use @objcMembers, otherwise, one-by-one add @objc. Simply use Xcode search to find out whether the Swift class is called from any .m file. This should make the conversion relatively painless.Offering
@Whose this should be accepted answer. Suppressing warnings and making things work as they were in Swift 3 is an option, but IMHO not the best one. It's important to understand why did @objc change in Swift 4 and then make decision to fix project and keep it the same.Erumpent
S
49

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

Standard answered 14/6, 2017 at 7:41 Comment(4)
So what should I do with @objc? remove it? leave it? I already did remove that. and the I gott those warning so I have to add them? that in step 3 should I do with that?Footed
Add @objc just before funcStandard
what step 3 is all about? You could add some descriptions :)Footed
And in my case, I get this warning, but no code is pointed to. There are two methods marked @objc and they seem like the only ones that need it. I changed it to Default and still get the warnings during compile.Sewn
D
12

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.

Dorthydortmund answered 16/3, 2018 at 22:46 Comment(1)
I wasted 20mins looking to solve the error even after I changed to Default in project settings. You pointed out exactly the it need to be changed in target also.Pinkham
P
8

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.)

Pinnatisect answered 2/7, 2017 at 9:12 Comment(0)
M
7

Indeed, you'll get rid of those warnings by disabling Swift 3 @objc Inference. However, subtle issues may pop up. For example, KVO will stop working. This code worked perfectly under 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. 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) enter image description here
  • Mark the affected methods and properties as @objc enter image description here
  • Re-enable ObjC inference for the entire class using @objcMembers enter image description here

Re-enabling @objc inference leaves you with the warnings, but it's the quickest solution. Note that it's only available for projects migrated from an earlier Swift version. 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

Memorialize answered 21/9, 2017 at 7:56 Comment(0)
G
7

I'm an occasional iOS dev (soon to be more) but I still couldn't find the setting as guided by the other answer (since I did not have that Keychain item the answer shows), so now that I found it I thought I might just add this snapshot with the highlighted locations that you will need to click and find.

  1. Start in the upper left
  2. Choose the project folder icon
  3. Choose your main project name below the project folder icon.
  4. Choose Build Settings on the right side.
  5. Choose your project under TARGETS.
  6. Scroll very far down (or search for the word inference in search text box)

Finding the setting

Giddens answered 18/11, 2018 at 17:52 Comment(0)
J
7

You can try to "Pod update" and/or "flutter clean"

I also set this setting in xcode.

The Objective-C interface setting is as follows:

ObjectiveC interface setting

Jervis answered 10/3, 2019 at 12:32 Comment(0)
B
2

Swift 3 @objc Inference 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 then disable inference by changing the "Swift 3 @objc Inference" build setting to "Default" for the "XMLParsingURL" target.

got to the

  1. First step got Build Setting

  2. Search in to Build Setting Inference

  3. change swift 3 @objc Inference Default

enter image description here

Bindle answered 28/9, 2017 at 16:1 Comment(0)
T
0

The use of Swift 3 @objc inference in Swift 4 mode is deprecated?

use func call @objc

func call(){

foo()

}

@objc func foo() {

}
Thorman answered 26/3, 2018 at 10:53 Comment(0)
A
0

All you need just run a test wait till finish, after that go to Build Setting, Search in to Build Setting Inference, change swift 3 @objc Inference to (Default). that's all what i did and worked perfect.

Apotropaic answered 17/12, 2018 at 19:59 Comment(0)
V
0

On top of what @wisekiddo said, you can also modify your build settings in the project.pbxproj file by setting the Swift 3 @obj Inference to default like SWIFT_SWIFT3_OBJC_INFERENCE = Default; for your build flavors (i.e. debug and release), especially if you're coming from some other environment besides Xcode

Vermeil answered 23/4, 2019 at 10:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.