Working with Objective-C and Swift on the Same Project

I know I’m a little late to the game, but I just recently started playing around with Swift, Apple’s new flagship language for developing apps for iOS, OS X and Apple Watch. Rather than starting a completely new project using only Swift, I thought it would be an interesting challenge to start with some Objective-C and try converting a class or two to Swift. Having heard that it’s possible to mix the two languages within a single project, I set out to see how difficult that would be. Here are a few things I learned throughout the process.

Carthage and CocoaPods

In my app, I wanted to try using the latest version of ReactiveCocoa, which has been recently rewritten in Swift.  ReactiveCocoa, along with many other open-source projects, has shifted to officially supporting Carthage, rather than CocoaPods, for dependency management.  Not knowing much about Carthage, one of the first questions that I had was whether it could be used alongside CocoaPods. It turns out the answer is yes.

Unlike CocoaPods, which reaches in and modifies your project files to include the paths to your dependancies, Carthage intentionally keeps its hands out of your project files. Carthage simply pulls down dependancies (using Git) and builds them into embeddable binary frameworks. It is left up to you, the developer, to take the compiled frameworks and embed them into your project as needed.

Because of this difference in philosophy and functionality, there should be no problem using both at the same time. That being said, it would obviously be ideal to use only a single dependency management tool if possible.

Adding Dependencies with Carthage

Adding dependencies to your project with Carthage is very straightforward.

  1. Add a Cartfile to your project root and tell Carthage where the repositories are located.
    github "ReactiveCocoa/ReactiveCocoa" "v3.0-beta.1" 
    git "https://any/git/repo/anywhere.git"
  2. Run `carthage update` to fetch the source files and build them, placing the output frameworks in the Carthage/build directory.
  3. Drag the framework file(s) to the ‘Embedded Binaries’ section of your project configuration, and you’re all set.

<p><strong>IMPORTANT</strong>: Carthage basically knows two things: <a href="https://git-scm.com/">Git</a> and Xcodebuild. It uses these for fetching and building dependancies. <strong>Make sure that you have the latest versions of these tools</strong> before you start using Carthage.</p>

For more information on setting up and using Carthage, turn to the project Readme file on Github.

Swift to Objective-C

As I mentioned earlier, part of my experiment was to see if I could use classes defined in Objective-C from Swift code. It turns out that is quite trivial. The first time you add a Swift source file to your project, Xcode will ask if you want to add a Bridging-Header file to your project. This file is used for importing Objective-C classes into Swift-land. All you need to do is add references to Objective-C header files, and you can begin using them in Swift.

If you’re interested in using Swift with plain C libraries, Matt Behrens wrote a very thorough Spin post detailing that process.

Objective-C to Swift

Leveraging Swift code from Objective-C is also possible, but it takes a little more work to set up.

First, open your project build settings and make sure the following are true:

  • ‘Project Module Name’ is set to a valid name that does not contain spaces
  • ‘Defines Module’ is set to ‘Yes’
  • The previous two are configured at the project level

Once you’ve completed the above configuration, you will be able to import Swift libraries,  write your own Swift classes, and access them in Objective-C as though they are normal Objective-C classes. Keep in mind that if you write a Swift class that is not a subclass of an Objective-C class, you must mark it with the @objc attribute in order to use it from Objective-C.

Bridging Types

Swift is more sophisticated and more advanced than Objective-C. For that reason, it has some types and features that cannot be bridged to Objective-C. The Tuple type is one such example. If you write a function that returns a Tuple in Swift, you will not be able to call that method from Objective-C. Below is a complete list of features which are excluded from Objective-C interoperability.

  • Generics

  • Tuples

  • Enumerations defined in Swift without Int raw value type

  • Structures defined in Swift

  • Top-level functions defined in Swift

  • Global variables defined in Swift

  • Type aliases defined in Swift

  • Swift-style variadics

  • Nested types

  • Curried functions

Resources

Want to learn more? The following pages contain a lot of helpful information about combining Swift and Objective-C in the same project.

Interacting with Objective-C APIs

Swift and Objective-C in the Same Project

Conversation
  • Colas says:

    Hi Jordan,
    Maybe you can help. I try to use Swift and Objective-C in the same Pod. I asked this question on SO: http://stackoverflow.com/q/41325193/1670830

    Thanks ;-)

  • Comments are closed.