Using Swift variables in Objective-C : Swift 4 Edition

Today I ran into weird problem which prompted me to write this blog post on Objective-C and Swift interconnectedness.

Before Swift 4 came along, the sure way to access Swift variables in Objective-C was to inherit class from NSObject (Swift structs cannot be used in the Objective-C) and prefix it with @objc keyword.

To summarize, below are the steps to import Swift classes in the Objective-C class

  1. Create a Swift class with class name prefixed with @objc annotation and inheriting from NSObject
  2. Xcode will autogenerate YourProjectName-Swift.h file with details of your Swift class intended to use in Objective-C
  3. You can import this header file in your Objective-C class to start using Swift class and variable
  4. Here's where it gets different in Swift 4. Steps 1-3 will work fine with pre-Swift 4 versions. However, if you want to start using Swift class and instance variables in Objective-C Swift 4 onwards, you will have to prefix them with objc keyword.
  5. Alternatively, if you have so many variables in Swift class and you want to make all of them available to Objective-C, you can add @objcMembers at the top of class declaration. This is equivalent to prefixing all the variables with @objc prefix
  6. Since rule has changed in Swift 4, you NO LONGER need to prefix Swift class with objc annotation

Let's see an example.

Assume below is the Swift class in project named MyProject you want to use in the Objective-C file. Let's begin by applying some of the

class Vehicle: NSObject {
    @objc let name: String
    @objc let numberOfWheels: Int
    let manufacturer: String
}

Observations:

  1. Class vehicle has 3 variables viz. name, numberOfWheels and manufacturer
  2. We derive Vehicle class from NSObject class
  3. Vehicle is a class and not a struct
  4. Instance variables name and numberOfWheels are prefixed with objc annotations to make them available to Objective-C classes
  5. Alternatively, if you want to make all the instance variables of Vehicle accessible to Objective-C, you can add @objcMembers before class declaration
  6. Let's assume the name of Xcode auto generated header file used to import Swift into Objective-C is MyProject-Swift.h

How to use:

  • Compile your project. This will add necessary Objective-C usable and compatible classes in the auto-generated header file MyProject-Swift.h
  • Import MyProject-Swift.h file in the Objective-C class. This is the same Objective-C class from which you want to access Swift class and related instance variables
  • Once this is done, you're good to use Swift class and related variables which are made accessible
Vehicle *vehicle = [[Vehicle alloc] init];
vehicle.name = @"RAV 4";
vehicle.numberOfWheels = 4;
// Please note that following line won't compile 
// unless you have used @objcMembers as explained above. 
// In normal case without @objcMembers keyword, 
// the Swift variable manufacturer is not visible to 
// Objective-C classes

// Do not use this.
// vehicle.manufacturer = @"Toyota";

This is all you need to know to start using Swift classes in Objective-C beginning Swift 4. Feel free to message me on @jayeshkawli on Twitter is you run into any other problems


References