Why is Swift 3 @objc inference becoming a thing of the past?
\n\nIf you've ever updated a project from Swift 3 to Swift 4, you've likely encountered the daunting compiler warning:
\n\nThe 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\nThis 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\nIn 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\nWhat is @objc inference and how did it work in Swift 3?
\n\nIn 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\nExample from Swift 3:
\n\nclass MyViewController: UIViewController {\n func buttonTapped() {\n print("Button tapped")\n }\n}\n\nIn 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.
Why did Apple decide to abandon automatic inference?
\n\nThere 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
What does the warning look like in practice?
\n\nLet'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\nclass 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\nThe compiler complains about legacyAction(), as it is not marked @objc, but previously the compiler did this automatically. Now a solution is needed.
Three ways to fix the warning
\n\nYou have three options. Choose the one that suits