Using Swift in an Existing Objective-C Project

Categories:

It’s clear from the Swift tutorials out there (including ours), that folks ask the question “How do I include Objective-C frameworks in my Swift project?” more often than “How do I include Swift code in my Objective-C project?” That’s understandable. Swift is new and shiny and we want to start off playing with Swift first and then mix in some Objective-C when we have to (which if you are using popular frameworks such as AFNetworking, Parse, etc., you have to quickly).

Since there’s plenty of Objective-C bridging header tutorials out there already, I thought I’d share my experience with the reverse direction: adding Swift code to an existing Objective-C project. I’d love to say it was easy and painless, but the reality is it was a pain in the ass (read this Stackoverflow thread to see why!).

Let’s start off the basic rule: Don’t add any Swift files to your project without reading this first. If you have already added Swift files and are scratching your head why things won’t work (namely that your -Swift.h can’t be found), delete them from your project and just start over and follow these steps:

Update Your Project Build Settings

Your project’s (not the target) build settings need to have the flag Defines Module set to YES. Go to your project build settings page and type Packaging in the search field and then set Defines Module to YES.

Screenshot 2014-11-26 16.04.46

Make Note of Your Product Module Name

Did you even know you had a product module name? I didn’t. To find it go to your target’s (not the project) build settings and again search for Packaging. Make note of the Product Module Name. In our case it is testing.

Screenshot 2014-11-26 16.10.33

Create Your Swift File

Create your Swift file with Xcode File – New – File. If Xcode asks whether or not you want to create a bridging header, you can if you like, but it’s not strictly required for what we’re trying to accomplish (Swift in Objective-C not the other way around, which is what the bridging header is for).

The Rules

There are rules around what’s required to get Swift objects living in harmony in your Objective-C code. For a complete overview see Apple’s documentation, but here’s what I’ve found to be true:

  • You have to #import <productModuleName-Swift.h> in every Objective-C class you plan to use your Swift classes in
  • The @objc declaration on a Swift class isn’t good enough – inherit from NSObject

The Header File

What others have pointed out in the Stackoverflow post referenced early is that unlike the the Objective-C bridging header the Swift bridging header is not a file you can see in your project, but is automatically generated in the build chain. That is, the compiler creates it as a temporary file prior to compiling your Objective-C. Even still, you have to #import it and if Xcode complains that it isn’t available you either don’t have Defines Module set to YES, or you named the header incorrectly (it is productModuleName-Swift.h, where productModuleName is your product module name), or (and here’s the irritating part) you added a Swift file to your project prior to setting Defines Module to YES.

The Swift Class Definition

Trying to use only @objc as an indicator that you’re going to use the Swift class in Objective-C code results in ARC complaints about alloc not being defined. Here’s a screenshot of declaring our Swift class like this:

Unfortunately we cannot compile due to the annoying No known class method for selector 'alloc' error:

Screenshot 2014-11-26 16.26.26

Changing our class to:

and the compilation proceeds and we can access our Swift class.

From there things proceeded relatively well. Our final test included the following Swift code:

with our delegate header including

and using it in our Objective-C application delegate:

As expected, our output:

Conclusion

If you can’t get Swift classes mixed into your Objective-C code on your first attempt, you’re aren’t an idiot. Future versions of Xcode one would hope will fix the annoying feature of failing to generate a -Swift.h header file if you didn’t do things in exactly the right order. In the meantime, follow these steps and definitely pore back over the Stackoverflow thread in case you missed something.

Leave a Reply

Your email address will not be published. Required fields are marked *