Migrate to Swift 4 @objc inference

Convert your code to use Swift 4 explicit @objc attributes to reduce overall code size.

To start the conversion process choose Edit > Convert > To Current Swift Syntax, choose the target in the sheet that appears, and then click Next. In the next sheet select an option for adding @objc attributes to your code where they were previously inferred implicitly.

  • Minimize Inference: Add an @objc attribute to your code only where it is needed based on static inference. After using this option you need to follow the manual steps detailed in Completing a Swift 4 minimize inference migration to complete the conversion.
  • Match Swift 3 Behavior: Add an @objc attribute to your code anywhere it would be implicitly inferred by the compiler. This option does not change the size of your binary as it adds explicit @objc attributes everywhere they were implicitly added by Swift 3.

For more information, see Configuring Swift Interfaces in Objective-C in Using Swift with Cocoa and Objective-C, and the entry for objc in The Swift Programming Language.

Completing a Swift 4 minimize inference migration

Sources converted using the “Minimize” inference option may require additional changes that are found using both build-time and run-time warnings. Follow these steps after you complete the initial Swift 4 migration.

  1. Build your project.
  2. Fix the warnings that indicate places where you need to add the @objc attribute.
  3. Test your code and fix warnings that indicate a deprecated implicit @objc reference is used. Continue to test your code until no warnings occur.
  4. Open the build settings for the project.
  5. Set Swift 3 @objc inference to Default.

Build Warnings: Swift

Warnings in Swift are of the form:

warning: argument of ‘#selector’ refers to instance method methodName() that depends on ‘@objc’ attribute inference deprecated in Swift 4

The following Swift code results in the warning shown below.

class MyClass : NSObject {
   func foo() {
   }
  
   func bar() {
      self.perform(#selector(MyClass.foo)
   }
}

warning: argument of ‘#selector’ refers to instance method ‘foo’ in ‘MyClass’ that depends on ‘@objc’ attribute inference deprecated in Swift 4

Build Warnings: Objective-C

Warning in Objective-C are of the form:

warning: Swift method ClassName.methodName() uses @objc inference deprecated in Swift 4; add @objc to provide an Objective-C entrypoint

The following Objective-C code results in the warning shown below

@implementation MyClass (ObjCMethods)
– (void)other {
[self foo];
}
@end

warning: Swift method MyClass.foo uses @objc inference deprecated in Swift 4; add @objc to provide an Objective-C entrypoint

Fix Build Warnings

To fix a warning, add an @objc attributed to the declaration of the function or other symbol that is identified in the warning.

Fix both of the warnings shown in the examples by adding and @objcattribute to the declaration of foo.

class MyClass : NSObject {
   @objc func foo() {
   }
  
   func bar() {
      self.perform(#selector(MyClass.foo)
   }
}

Runtime Warnings

Runtime warnings appear in the console and are of the form:

***Swift runtime: ClassName.swift:lineInFile:columnInLine: entrypoint -[ClassName methodName] generated by implicit @objc inference is deprecated and will be removed in Swift 4; add explicit @objc to the declaration to emit the Objective-C entrypoint in Swift 4 and suppress this message

To fix a warning add an @objc attributed to the declaration of the identified function or symbol.

The most common reasons for the warning are:

  • Use of SEL in Objective-C.
  • Using one of the perform methods in Swift.
  • Using one of the performSelector methods in Objective-C.
  • Using an @IBOutlet or @IBAction.

The following Swift code results in the run-time warning shown below.

class MyClass : NSObject {
   func foo() {
   }
  
   func bar() {
      let selectorName = "foo"
      self.perform(Selector(selectorName)
   }
}

***Swift runtime: MyClass.swift:7:7: entrypoint -[MyClass foo] generated by implicit @objc inference is deprecated and will be removed in Swift 4; add explicit @objc to the declaration to emit the Objective-C entrypoint in Swift 4 and suppress this message

Leave a Reply