Swift 3 @objc inference deprecated: what to do in Swift 4

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Why is Swift 3 @objc inference becoming a thing of the past?

\n\n

If you've ever updated a project from Swift 3 to Swift 4, you've likely encountered the daunting compiler warning:

\n\n
The use of Swift 3 @objc inference in Swift 4 mode is deprecated. \nPlease address this deprecated @objc inference warning, \nor disable the warning by setting the "Swift 3 @objc Inference" \nbuild setting to "Default" for the "Swift 4" target.
\n\n

This message is not just a formality. Behind it lies an important change in the language's philosophy. In Swift 3, the compiler itself decided which methods and properties should be visible to Objective-C. This was convenient, but it created hidden problems: binary size grew, and performance suffered. Swift 4 decided to put an end to this "guesswork" and handed control over to the developer.

\n\n

In this article, we'll break down what @objc inference is, why it was deprecated, how to fix the warning, and what best practices to use in modern projects. Let's go!

\n\n

What is @objc inference and how did it work in Swift 3?

\n\n

In Swift 3, there was an implicit conversion to @objc. This meant that if a class inherited from NSObject or used an @objc protocol, the compiler would automatically make all its methods visible to Objective-C. This mechanism was called @objc inference (implicit inference).

\n\n

Example from Swift 3:

\n\n
class MyViewController: UIViewController {\n    func buttonTapped() {\n        print("Button tapped")\n    }\n}
\n\n

In Swift 3, the method buttonTapped() automatically became @objc. You could pass it to #selector or use it as a target for UIControl. Convenient? Yes. But the price was unjustified binary bloat and loss of optimizations.

\n\n

Why did Apple decide to abandon automatic inference?

\n\n

There are several reasons, and they all come down to efficiency and control:

\n\n
    \n
  • Application size. Every method marked as @objc generates an additional wrapper for the Objective-C runtime. In large projects, this could add megabytes of extra code.
  • \n
  • Performance. Swift is a language with static typing and powerful optimization. As soon as a method becomes @objc, the compiler loses the ability to apply a number of optimizations (e.g., inlining).
  • \n
  • Explicitness. Swift 4 took a course towards explicitness. The developer must decide for themselves what should be accessible from Objective-C. This simplifies code understanding and reduces unexpected errors.
  • \n
  • The future of Swift. Apple is gradually moving away from dependence on Objective-C. The fewer implicit bridges, the faster Swift can become a fully independent language.
  • \n
\n\n

What does the warning look like in practice?

\n\n

Let's say you have a project written in Swift 3. You switch the "Swift Language Version" setting to Swift 4.0 and get dozens (or even hundreds) of warnings like this:

\n\n
class LegacyViewController: UIViewController {\n    // Warning: The use of Swift 3 @objc inference in Swift 4 mode is deprecated\n    func legacyAction() {\n        // ...\n    }\n\n    @objc func explicitAction() {\n        // This method is already marked @objc — everything is fine\n    }\n}
\n\n

The compiler complains about legacyAction(), as it is not marked @objc, but previously the compiler did this automatically. Now a solution is needed.

\n\n

Three ways to fix the warning

\n\n

You have three options. Choose the one that suits

Blogs

Book Recommendations