Basic Overview of Static and Dynamic Frameworks on iOS

Written by Valentyn Kuznietsov, iOS Developer Engineer Cardio 1
Applications tend to grow and so does their source code. Hence, structuring the codebase into manageable components is a vital part of every app. This is done for various reasons: reducing code complexity, maintaining and reusing existing parts or even optimizing the app itself.
On iOS we have various ways of packaging and delivering such components. All the options can leave a developer wondering what the differences between the various methods are. Even though every term deserves its own article, we will try to highlight the main differences between the most common terms in this article.
Dynamic and static libraries
First of all, a library is a collection of resources and the code itself, compiled for one or more architectures.
Let’s briefly touch on what dynamic and static libraries are and clarify the main difference. The word static or dynamic refers to the way the compiled code is referenced by the target application.
In the case of static libraries (*.a), the code that the app uses is copied to the generated executable file by a static linker during compilation time.
Dynamic libraries (*.dylib) are different from static libraries in the sense that they are linked with the app’s executable at runtime, but not copied into it. As a result, the executable is smaller and, because the code is loaded only when it is needed, the startup time is typically faster.
Dynamic and static frameworks
For frameworks, we first need to understand the bundle concept (as a framework is a specific kind of a bundle). A bundle is a file directory with subdirectories inside. On iOS, bundles serve to conveniently ship related files together in one package – for instance, images, nibs, or compiled code. The system treats it as one file and you can access bundle resources without knowing its internal structure.
The library may also have additional resources: headers, localization files, images, documentation and examples of usage. We can bundle all of this together in one bundle – and the name of this is framework.
Static frameworks contain a static library packaged with its resources. Dynamic frameworks contain the dynamic library with its resources. In addition to that, dynamic frameworks may conveniently include different versions of the same dynamic library in the same framework!
What are embedded, umbrella, modular and fake frameworks then?
Although we ship frameworks with resources inside (such as XIBs and images), Xcode will still ignore some of them. By embedding the framework we can use these resource files. To embed a framework, just click on your target in the Xcode and add your framework in the “Embed Frameworks” section.
The main purpose of umbrella frameworks is to hide complex dependencies between frameworks from a developer. It allows you to ship several frameworks as one framework, exposing only some of the headers to the target application. In order to build an umbrella framework, you have to include the umbrella header, which is nothing more than a regular header file with selected imports; these are important for a framework user.
To be able to call a framework modular, one must include the module map:
framework module ModularFramework { module Module1 { header "File1.h" } module Module2 { header "File2.h" } }
Subsequently, this will allow you to import only the modules you need:
import ModularFramework.Module1 import ModularFramework.Module2
The CocoaPods dependency manager actively uses umbrella and modular frameworks. If you integrate some pods into your project, you just search for the “modulemap” and “umbrella” keywords in the project and see what they look like.
A fake framework is a common technique of “transforming” a bundle into a framework. For instance, when you create your own framework and use a 3rd party library inside, you can ship your code and 3rd party library together (as one framework). To achieve this, there are some open-source scripts available.
Some questions and answers
Some typical questions that arise frequently could be answered once you understand frameworks on iOS better.
Question: Can we load code from dynamic frameworks during runtime?
Answer: Not if you develop for the App Store. The main reason is that Apple does not allow modification of app behavior after review, which would be possible with dynamic frameworks.
Question: Can we create static frameworks using Swift?
Answer: Finally, YES! (Xcode 9). CocoaPods announced the support of Swift Static Frameworks in 1.5.0, but you can already fork the CocoaPods source code and integrate all your dependencies as static frameworks if needed.
Question: How many dynamic frameworks can I use?
Answer: We recommend trying to limit them to a dozen. However, it is almost always impossible and they can easily exceed one hundred. Still, try not to create too many dynamic frameworks (consider combining them) and use static frameworks instead.
If you are curious, one of our biggest apps – Runtastic – had almost two hundred dynamic frameworks at some point, and we applied some measures (e.g. moving selected parts of the code from frameworks to the app itself or merging the frameworks) to reduce that number drastically.
Conclusion
We hope that this short overview will help you navigate through all these terms with ease. Now you can understand every word if you ever see the embedded modular umbrella dynamic fake framework in one sentence!

***