Swift and Objective-C Interaction

Swift and Objective-C Interaction

In this post I am going to write how you can use Swift code in Objective-C and vice versa. I have run into this problem multiple times and every time I hit the wall. More importantly this post acts as a self reference to myself so that I can save some time for myself without searching it all over on StackOverflow.

  • Using Objective-C code in Swift

Firs thing first, we will see how you can write Objective-C code and use it in the Swift. First off, create a sample project in Swift. Xcode will generate few files in Swift, but don't worry - We can still create Objective-C files manually and use it in Swift

sample_project

Next, add a new Objective-C file and name it as ObjectiveCSampleFile. During creation, Xcode will ask if you need to create bridging header or not. Select an option Create Bridging Header and proceed

To quote Apple,

To import a set of Objective-C files in the same app target as your Swift code, you rely on an Objective-C bridging header to expose those files to Swift. Xcode offers to create this header file when you add a Swift file to an existing Objective-C app, or an Objective-C file to an existing Swift app.

In case your project has Swift and Objective-C files, but it does not have bridging header, worry not. You can go through this answer on StackOverflow which has step by step explanation on how to manually add bridging header in the project

bridging_header_prompt

Next step is to add a sample code in ObjectiveCSampleFile header and implementation file as follows

// Header file
@interface ObjectiveCSampleFile : NSObject

- (void)doIt;

@end
// Implementation file
#import "ObjectiveCSampleFile.h"

@implementation ObjectiveCSampleFile

- (void)doIt {
    NSLog(@"Doing It!!!");
}

@end

Now go to LanguageInterOperability-Bridging-Header.h and import your Objective-C file in the bridging header. The code will look like this,

//
//  Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "ObjectiveCSampleFile.h"

Now any Swift file in your project is ready to use Objective-C code. Say I want to use doIt method in foo.swift file so I can type like this,

let sampleCode = ObjectiveCSampleFile()
sampleCode.doIt()

Remember, there is no need to import Bridging header file. As long as your Swift file and bridging header remain under same module, you are good to do.

  • Using Swift code in Objective-C

    Swift code can be used in the Objective-C class using file named $(SWIFT_MODULE_NAME)-Swift.h. For example in our current project file will be named as LanguageInterOperability-Swift.h. Any Swift method you will write will be directly imported into this header file in the form of Objective-C source code and will be subsequently used to use Swift code

If you want to verify the existence of this $(SWIFT_MODULE_NAME)-Swift.h in your project, go to Build Settings and search for -swift. If this file exists, you will see result result similar to following,

search_swift_method

If you don't already have this Objective-C generated interface header file, worry not. You can manually create a
this file in the form of module_name-Swift.h. (If your project contains spaces, replace them with underscores while naming interface header file e.g. Awesome Pro becomes Awesome_Pro-Swift.h). Once file is create, add its path under Objective-C interface header file path in Build Settings as follows

Objective-C-interface-header-file

Once the interface header file for Objective-C code is ready, you are ready to use Swift code in Objective-C code.

// Import the generated header file
#import "LanguageInterOperability-Swift.h"

// Use the Swift code
ViewController* vc = [[ViewController alloc] init];
[vc swiftMethod];

That's it, and now you know how interoperate these two amazing languages in the same project. Some caveats though while importing Swift code in Objective-C

  1. To use Swift code in Objective-C, classes must be annotated with @objc or should inherit from NSObject (e.g. @objc public class HelloWorld: NSObject)

  2. You cannot use auto generated Objective-C header file in header file of Objective-C code. The compiler will complain that header file does not exist in the project

  3. There are certain things that cannot be transformed from Swift to Objective-C. Such as generics, swift specific classes and methods, optional primitive types (var val: Int?) and structs etc. Make sure you code handles these exceptions while trying to make Swift code available on Objective-C platform

If you want to save some time exploring now it all works and want to directly play with the code, I have added the example code on the Github repository. The demo shows how to call Swift method from Objective-C and vice versa

Thank you for going through this post. If you have further questions about interoperability between Swift and Objective-C code, please let me know. I will keep updating this post as I find any other gotchas while dealing with interoperability

References:

Bridging headers creation

Mix and Match Cocoa apps

How to import Swift code to Objective-C