Are you Duplicating a piece of code for a particular functionality across multiple Apps? Do you find it difficult to fix a bug on all those places? If Yes, then Static Library is an answer to your problems.
When the going gets tough, the Static Library gets going 🚀
- Shahrukh Alam
What is a Static Library
It’s nothing fancy, but a collection of compiled source code files to achieve a particular functionality.
Let’s say we have FileA.swift, FileB.swift & FileC.swift, then we can compile them & wrap them together to form a Static Library which will have an extension of .a (short for Archive). Simply put, it’s like:
Fig: Static Library Packaging
Why to use it
Code Reusability: Suppose we have a common piece of functionality across multiple Apps, we can create a static library out of those common source codes & share across all our Apps instead of duplicating them.
Code Abstraction: We can hide the code which shouldn’t be known to the client App by marking Headers as Private or Internal.
Code Encapsulation: By distributing just the Static Library Binary (will discuss on later part of this Article), we can just share the functionalities & hide the implementation details from the clients.
Ease of Use: Clients shouldn’t worry about the nitty-gritty of the functionalities, They should get just the bare-minimum with the least effort.
Maintainability: When we have a central place for all our code, we can easily fix a bug & share it with the clients with just a version bump.
Reduce App Compile Time: By distributing just the Pre-Compiled Static Library Binary, we can reduce the compile time of the App compared to compiling all those source files needed for the piece of functionality.
Reduce App Launch Time: The way Static Libraries work (will discuss on later parts of this Article) compared to Dynamic Frameworks, we can minimise on dylib loading time of Pre-main time which helps in faster App Lauch.
How to create one
We are going to create a Static Library called Painter which can paint a random color on a View passed by the Client App.
Responsibilities of Painter
Logic to generate a random color
Logic to paint it on a View passed by the Client App
Step 1
Step 2
Step 3
Step 4
Step 5
Let’s Build for Simulator, we would see something like this on DerivedData Folder of Xcode.
Step 6
Let’s Build for Generic iOS Device, we would see something like this on DerivedData Folder of Xcode.
What are the contents of a Static Library
As discussed earlier, Static Library is nothing but:
Fig: Static Library Packaging Flow
We can use ar tool to see the Object Files inside the libPainter.a:
Fig: Contents of a Static Library
We can use nm tool to see the Symbols (eg: Types & Functions) declared inside the libPainter.a, notice the first one in Painter.O is for our only public function paintRandomColor(onView view: UIView)
Fig: Symbols contained in a Static Library
How to use it in a Client App
Step 7
(in continuation to previous steps)
Step 8
Step 9
Step 10
Let’s create a folder named StaticLibrary somewhere safe(say Desktop) & copy the .swiftdoc
& .swiftmodule
files from both the Debug-iphonesimulator & Debug-iphoneos folders of Painter Static Library.
This folder will be needed to integrate the Static Library in the Client App.
It should look something like this now:
.swiftdoc
& .swiftmodule
files basically mimic the Objective-C Header for a Swift Module.
Step 11
Let’s create a Universal Binary or a Fat Binary which can work for both the iOS Simulator & iOS Device using lipo tool using command:
lipo -create path_to_archive_for_simulator path_to_archive_for_device -output path_for_universal_binary
Universal Binary = libPainter.a from Debug-iphonesimulator + libPainter.a from Debug-iphoneos
Now our StaticLibrary folder should look something like this:
This folder is all that’s needed to integrate the Static Library in the Client App. Now we can distribute this folder to our Clients.
Step 12
Let’s Copy & Paste the StaticLibrary Folder from the previous step into the PainterClientApp root directory.
Step 13
Let’s Add libPainter.a to Link Binary with Libraries of App Target Build Settings.
Video: How to link Static library to the App
Step 14
Let’s Set $(SRCROOT)/StaticLibrary as LIBRARY SEARCH PATHS
& IMPORT PATHS
of App Target Build Settings
LIBRARY SEARCH PATHS
A list of Folders(or Paths) which Xcode(rather Linker) will search for Library(.a) Files. You may already know about FRAMEWORK SEARCH PATHS, it’s similar to that, but for Libraries.
IMPORT PATHS
A list of Folders(or Paths) which Xcode(rather Compiler) will search for additional Swift Modules. You may already know HEADER SEARCH PATHS, It’s similar to that, but for Swift Libraries.
Step 15
Let’s import Painter
& use the paintRandomColor
method from the Static Library in ViewController.
Step 16
Let’s Build & Run the App in both the Simulator & Device. We can see different random colors on every launch.
Video: Demo of App using Static Library
Step 17
Let’s check if Archive also works, if we would see the contents in the Archive by Show Package Contents, then Products -> Applications -> Show Package Contents for PainterClientApp, then we would find no sign of our Painter Static Library. That’s because it’s sitting right inside the App Binary. We will understand this in more detail in the next section.
How it works
Let’s check for Show Package Contents for our PainterClientApp first.
Fig: Contents of App Package
Even if we just linked libPainter.a to our App Target, it got copied into App Binary. That’s because of Static Linking of the Library.
Fig: Static Library Linking
So, now when System loads our App, it loads the Static Library Functionality as a single App Executable. Hence, the faster load/launch time.
When not to use it
Static Libraries are great for code reusability and abstracting things. But, it has few demerits compared to it’s counterparts: Dynamic Libraries & Dynamic Frameworks.
Higher App Size: As Static Library Object Files are directly copied to the App Binary, app size is bloated. Dynamic Libraries are loosely linked to the App, whereas Static Libraries are hard linked to the app. For instance System Frameworks like UIKit are loaded when needed, App just keeps a reference to it, hence doesn’t add to the App Size which Users are going to download on their precious Network.
Resources: As Static Libraries are just a collection of Source Code, it can’t have Resources like Assets, Xibs, Storyboards & JSONs which are essential for many functionalities. Distributing Static Library along with a Resource Bundle solves this problem to a great extent, but Dynamic Frameworks really shine here.
Conclusion
In this post we have learned how to leverage the use of Static Libraries to bundle up common functionalities across multiple Apps, how it will reduce duplicity & help maintainability. We have also put some light on the areas where Static Libraries don’t shine compared to Dynamic Libraries & Frameworks.
Try to figure out the scenarios where you can make good use of them for a Cleaner, Sharable & Maintainable Approach.
You could find the full code on Github: PainterStaticLib, PainterClientApp