In the world of programming, libraries are self-contained codes and resources that can be used for modularizing and reusability. In Xcode, we can define frameworks, static and dynamic libraries and bundles to modularize our codes and resources. Unfortunately it is somewhat vague in Apple documentations. So let’s look at their differences and purposes in a simple word.
Libraries can’t include resource files: images, assets, nibs, strings file and other visual data. It can be worked out by encoding these resources into data and decode them at run-time. This is a headache. We can also create a bundle besides the libraries and ship the bundle and library together. Creating stand-alone bundles is not supported for iOS. In iOS we can only access the resources containing in another framework as a separate bundle.
We can create two types of libraries, Static and Dynamic.
- Static linker links the static library at compile-time.
- They Can’t contain resources. They carry only codes.
- They can’t contain resources. They carry only codes.
- Dynamic linker links the dynamic libraries at run-time.
- Dynamic libraries outside of a framework bundle, which typically have the file extension .dylib, are not supported on iOS, watchOS, or tvOS, except for the system Swift libraries provided by Xcode, such as Core Data, Core Bluetooth, which belongs to Apple.
System iOS and macOS libraries are dynamic. This means that your app will receive improvements from Apple’s updates without new build submission. This also may lead to issues with interoperability. That’s why it is always a good idea to test the app on the new OS version before it becomes released.
A framework is a bundle (a structured directory).
- Frameworks contain dynamic shared libraries.
- They also contain resources, such as nib files, image files, and header files.
- Dynamic linker links the dynamic library of framework at run-time.
Frameworks intended for the same purposes as a static and dynamic shared libraries. But unlike libraries, frameworks:
- can include resources like images, assets, documentations, strings files.
- only one copy of framework read-only resource loaded to memory, that allows to decrease memory footprint and share framework between iOS app and extensions.
How to check if a module is dynamic or static?
Select the module target and in the build settings search for “Mach-O Type” item. It shows frameworks are dynamic libraries. You can change them to static libraries. In this case you will not have access to the framework bundle and can’t use resources inside the framework.
Embed or Not embed?
Embedding a module, adds that module as a folder in the final package. We can access the resources inside this folder using the Bundle class at runtime. To see that folder practically embed a framework in your app and archive it. Then find your archive and select “Show Package Contents”. Find your app in the Products > Applications and again “Show Package Contents”. You will see there is the “Frameworks” folder. If you do not embed a dynamic framework, your app will crash on real devices which is clear. I don’t know why but it still works on simulator. So there is no way except embedding dynamic libraries.
There is no need to embed static libraries because those are compiled and linked to the application at compile time.
In terms of app startup performance, the static libraries can be faster because they are linking at compile-time. So they do not need to be linked at runtime. Loading all dynamic libraries at startup may slow down the app start time.
On the other hand, static libraries increase the size of the app binary file. Because those are included in the app binary at compile-time. Furthermore, dynamic libraries can be shared between iOS app and its extensions. So it can decrease the size of app.