Testing Mixed Swift and Objective-C code

I’ve been working with a Swift project, and recently decided to add MMWormhole to it. This is the first Objective-C code to be added to this project, so I needed to review the Apple WWDC 2014 videos and developer documentation to figure out how to that.

It appears at first glance that the process is very simple. At least, it should be. What I ran into though appears to be bugs in Xcode.

The first bug I ran into was a problem with the prompt to automatically create the bridging header. When an Objective-C file is added to an all-Swift project, Xcode is supposed to ask you if you’d like a bridging header to be created, and then do so. This didn’t happen, but it’s no big deal. The bridging header can be easily created manually. This is pretty simple, but may not work depending on whether you hit the second bug I ran into, described further on.

  1. Create a new header file. Name it -Bridging-Header.h (substituting with the name of your project)
  2. Search for the “Objective-C Bridging Header” setting, and set its value to point to the file just created
  3. Repeat step 2 for the test target if you’re going to do any testing that needs to reference the Objective-C code also. This shouldn’t be necessary in most cases, but I needed to do so in order to write a unit test to try to catch the second bug.

The second bug is much worse. It appears that once a project starts getting bigger or more complex, the bridging header just stops working. By that I mean that the objects included using the bridging header (MMWormhole in my case) stop being found, even if previously building ok.

I’m in the process of recreating my project to try to determine exactly what steps cause the bridging header to stop working. I’ll update this post once I’ve found it.

Update 3/11/15

A friend of mine ran into an issue when trying to test a Swift class that had been added to his otherwise Objective-C project. Since he already had a good suite of Objective-C tests, he simply wanted to add an Objective-C test. This caused various compile errors. The solution was to add the Swift file to the test target.

By default, tests are run as “application tests”. This means that the tests are injected into the application. Hence tests have access to everything in the application. However, Swift files are compiled into a separate module during the build process, and thus not visible to the test target. You can think of this as meaning that Swift files are in effect run as “library tests”, and thus must be added to the test target to be visible.

2 thoughts on “Testing Mixed Swift and Objective-C code

  1. I’m interested in getting MMWormhole working in Swift too but am wondering if it’ll just be easier/cleaner to rebuild each step in Swift myself. I think I understand the process & key concepts for doing so:

    1. The user opens the Watch app
    2. The Watch wakes up the iPhone app in the background with openParentApplication:Reply: and asks for some data
    3. The awoken iPhone app gets and saves the data to an App Group
    4. The iPhone notifies the Watch that it has sent the data using CFNotification Center Darwin Notifications

    I already have AppGroups working but haven’t tried openParentApp or Darwin yet. Curious what you think. Thanks!

  2. Great post, thanks.
    But I have a problem. If some objC file uses swift file it must #import generated file “-swift.h” to use swift class interface. So this file is generated by main target and I have no idea how to make swift classes visible in test target.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.