Objective-C and Swift mixed modules

Say you have an Objective-C static library named ObjectivelyStatic and a dynamic Swift framework named DynamicallySwift and you want to make both available in an app that contains both Objective-C and Swift code. Lets call the app Gizmo for example purposes. The catch is that DynamicallySwift also needs to export some of it's own Objective-C code. Things are getting complicated from the module perspective if you want to use ObjectivelyStatic and DynamicallySwift in both your Objective-C and Swift code in your Gizmo app.

How do we make it happen?

First, you need to create an umbrella header and module map for ObjectivelyStatic. I am not going to cover that here, but there are some great resources like Sam Symons' post on the subject.

I'll wait here while you modularize.

Now that you have modularized your static library you need to link ObjectivelyStatic to DynamicallySwift. To remain package manager neutral we will do this the old fashioned way. I like to create a Xcode workspace to contain my project. I usually create a parent directory for the project, place the workspace in the parent directory and then check out the repositories for each library/framework/app in the directory. Then add them to the workspace.

Two pro tips: 

  • Static libraries sometimes need a Header phase added to the Build Phases for the target. You will want to make your umbrella header and any exported headers public using that.
  • In your dynamic framework add `-force_load $(CONFIGURATION_BUILD_DIR)/libObjectivelyStatic.a` to your Other Linker Flags in your dynamic framework to get all your static lib symbols linked in.

Once in the workspace, in DynamicallySwift framework target, add ObjectivelyStatic to the Linked Frameworks and Libraries section. Then, in Build Settings, add the path to the module map parent directory to Header Search Paths and to the Swift Compiler Import Path. Tada! You have made ObjectivelyStatic a proper module that can be used in DynamicallySwift in both Swift and Objective-C files.

Finally, in your Gizmo App target, embedded DynamicallySwift as you would any other dynamic framework. In the Gizmo App target, add the same Header Search Path and Swift Compiler Import Path as you did in DynamicallySwift. Boom! You have access to both ObjectivelyStatic and DynamicallySwift in both Swift and Objective-C files in your app.

You can find an example here.