With the release of Cocoapods 1.5, you can now compile all your pods as static libraries, even if some or all of them use Swift. This means that instead of building them as dynamic frameworks which are loaded when your app launches, the code is combined with your app binary at compile time. This can improve app launch times and the download size of your app if you depend on a lot of pods.
The conversion is relatively straightfoward:
- Remove
use_frameworks!
from your pod file. If all your pods are purely Swift, this should be all you have to do. - Otherwise, you might have to either add
use_modular_headers!
to the top of your Podfile or individual targets. Alternatively, you can add:modular_headers => true
to each pod that throwing errors during build.
That’s it as far as your Podfile is concerned. Now, when I was doing this conversion, I raw into two errors with one of my apps. I’ll describe how I fixed them and hopefully that will help you if you find yourself in a similar situation.
Could not build Objective-C module X” and/or “‘X.h’ file not found
I ran into this with Urban Airship’s Notification extension SDK. When you create a Swift library/framework in Xcode, it creates a .h file for the module that recommends to import headers in the format #import <[Project or Module]/X.h>
. This needs to be changed to #import "X.h"
in order for compilation as a static library to work. I submitted a PR to Urban Airship and they put the fix in their next release.
Module ‘Fabric’ has no member named ‘with’
If you using Fabric/Crashlytics, you might get this error where you are initializing Fabric. In my case, I was also using Firebase which imports Fabric (and crashlytics) headers in some of their C/++ code. By adding import Firebase
to the same file where I’m importing and using Fabric, I was able to work around this error. I’m not where best to apply a proper/permanent fix at the moment.
Smaller binaries
As I said above, making this move can decrease the size of your app. In my tests, the overhead per dynamic library/framework is about 100kb for a thinned (device specific) app, and over 300kb for a universal app binary. One of my apps uses over a dozen pods, so this presents quite an improvement.
I hope this guide was helpful. If something isn’t clear or you’re running into a problem I didn’t address, feel free to reach out to me on Twitter.