Frameworks: embed or not embed that’s the question

this is the head image of the framework tutorial about embed or not and about signing or not the modules

Hello, my fellow peers, Leo here. We will study how to embed or not embed a framework like static and dynamic libraries in your architecture.

Today we’ll explore one thing that I recently discovered and I want to share with you all. When you create a framework in iOS development it can be various things, today we’ll focus on only two of those options – a static library or a dynamic library. The advantages of modularization are plenty: development can be divided, you have more readable programs, programming errors (or features who knows?) are easy to handle, it allows re-use of code, you have improved manageability, and so on.

It’s not new that creating frameworks is a good strategy for big teams because they have literally hundreds of thousands of lines of code to maintain, so it’s important to have it neatly done to don’t become a really big mess. And isn’t in the scope of this post what the advantages and the disadvantages of using frameworks are, this might appear in some later writings.

The painting that I picked for this article is Hamlet and Ophelia by Agnes Pringle (1853–1934) and the reference is the “to be, or not to be, that’s the question” from the famous masterpiece that I put not *secretly* in the title.

Let’s go!

 

Problem – Frameworks: embed or not embed that’s the question

I want to know what is a better strategy for my newly created framework, it’s better static or dynamic? Embed or not?

First, for this topic, we’ll need some theory about what are the advantages and disadvantages of each one of the choices and after that, I’ll show you an example of each one.

 

Dynamic Library vs Static Library

The main difference between those two is how each one is linked to the executable file.

Dynamic libraries as the name says are dynamically linked to the application, they are not part of the application executable file. It means that when the app will load all of them in runtime, you might be thinking exactly the same thing as me right now “But if it’s a runtime load if I add a lot o dynamic libraries into the project and all or the majority of them be loaded in the startup, this could be a problem.” AND you are correct as commented at this WWDC16 talk it’s not a good idea to have a lot of dynamic libraries inside your app.

The process goes like this: When an app is launched the code is first loaded into the target address space. Then the dynamic linker comes into play, linking everything that the app needs to work properly. The dynamic linker will resolve each dependency location on the file system based on their install name and then link the undefined external symbols ( in this case the code that you are relying on) to your app.

On the other hand, the static library when linking will use the static linker. That means when at the build time you are using such a library the linker will merge in one single executable file all the framework code and the target application code. This way your final executable will be bigger but you guarantee that all the code needed to run, is already available to use. When the application launches all the application code plus the framework code will be loaded in the application address spaces.

 

Framework

In the Apple world, the frameworks can be various things. The Apple documentation says:

A framework is a hierarchical directory that encapsulates shared resources, such as a dynamic shared library, nib files, image files, localized strings, header files, and reference documentation in a single package. Multiple applications can use all of these resources simultaneously. The system loads them into memory as needed and shares the one copy of the resource among all applications whenever possible. […] Frameworks serve the same purpose as static and dynamic shared libraries, that is, they provide a library of routines that can be called by an application to perform a specific task.

After you create a framework, how can you tell if your framework is a static library, a dynamic library, or something else?

To answer this question you need to search for the Mach-o-type inside your framework, like the image below.

Frameworks: embed or not embed that's the question, dinamyc and static libraries image 1

You just need to go in your target -> build settings -> Linking -> Mach-o-Type. You can CHANGE the type of the framework to any other options. When you create a framework from Xcode it’ll automatically set it to a dynamic library, but you can change it for whatever you want, as the image below shows.

Frameworks: embed or not embed that's the question, dinamyc and static libraries image 2

For the example of this post I just created a plain new framework with the “command + shift + n” shortcut.

Frameworks: embed or not embed that's the question, dinamic and static libraries image 3

 

Embedding (or not) a framework

When you create an app you can have multiple frameworks and dependencies in it. All of them you can set in the General tab in the Target of your choice. As the image below suggests:

Frameworks: embed or not embed that's the question, dynamic and static libraries image 4

Frameworks have these three choices: Do not Embed, Embed & Sign and Embed Without Signing.

Frameworks: embed or not embed that's the question, dynamic and static libraries image 5

Do not Embed

With the “Do Not Embed” choice you are literally saying: please don’t pack all the contents of this framework with the main application. This implies that the final application package will not contain a folder called (by default) Frameworks with all the framework code.

But wait… early you didn’t say that the **dynamic library** is loaded outside the application code in runtime? Yes, and if you have a framework with the mach-o-type **dynamic library** and in the project **”do not embed”** when your app tries to dynamically find the dependency inside the package it will give you a runtime error. So be careful with this. And yes, Apple could check if you are doing this kind of thing but all we have now is hope that this could be an Xcode feature for the future.

Still talking about the “Do Not Embed”, if you do not embed a framework that is mach-o-type **static library**, your code will run normally because the code inside the framework when you archive is statically linked to your main code, this means the code inside the framework was packed together inside the application code. Therefore, you don’t need to embed it to your app unless you want to have access to some “media bundle” inside the static library framework that you are using.

Obviously, when you don’t embed the framework code your final “.ipa” will be smaller, but in the case of the dynamic library, you don’t have the choice of not embedding them.

 

Embed framework (signing or not)

The “Embed and Sign” and “Embed Without Signing” the only difference is if you need to sign the framework or not. It is already signed you don’t need to sign it again (ad hoc doesn’t count on this).

Embedding a framework that mach-o-type is a dynamic library you are assuring that all the files of that framework will be available in the final bundle of the app. When the app try to resolve the external symbols that are not inside the main app code it will find them inside the app bundle in the framework folder. As explained above, this could affect seriously your startup time so be careful with dynamic linking.

Now finally, when embedding a framework with mach-o-type of the static library is something that you might rarely do. If you already have your code inside the main app executable you actually will “duplicate” the size of your dependencies embedding a static framework on your app.

If for some (out-of-your-control or not) reason you need to get access to the “media bundle” inside the static library you can do it by embedding the static framework to your final bundle, but keep in mind the “size duplication” problem stated above.

 

TL;DR

Now you will be able to compare the main differences between those four options in a single view.

Frameworks: embed or not embed that's the question, dynamic and static libraries image 5

And now let’s go to the example app that shows the final size differences of each one of the options listed above.

 

Exempli Gratia – Code Setup

For the setup, I create a simple app that has one ViewController that I want to have all the options to choose the color from another framework that I will create. The application is called BundleForAllExample and the framework I will create is called MyColors.

The application code is pretty straightforward. Just create a new app and paste the code below to the ViewController.swift archive.

import UIKit
//import MyColors // mark 1

class ViewController: UIViewController {
    
    private var titleLabel: UILabel!
    private var pressMeButton: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        //view.backgroundColor = UIColor.Material.blueA100 //mark 2
        view.backgroundColor = .blue
        configureTitleLabel()
        configureButton()
    }
    
    private func configureTitleLabel() {
        titleLabel = UILabel()
        view.addSubview(titleLabel)
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        titleLabel.text = "THIS IS JUST AN EXAMPLE"
        
        NSLayoutConstraint.activate([
            titleLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 30),
            titleLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        ])
    }
    
    private func configureButton() {
        pressMeButton = UIButton()
        view.addSubview(pressMeButton)
        pressMeButton.translatesAutoresizingMaskIntoConstraints = false
        
        pressMeButton.setTitle("Press Me", for: .normal)
        pressMeButton.setTitleColor(.black, for: .normal)
        pressMeButton.backgroundColor = .yellow
        
        NSLayoutConstraint.activate([
            pressMeButton.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 20),
            pressMeButton.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        ])
    }
}

You should see this:

Frameworks: embed or not embed that's the question, dynamic and static libraries image 7

But what you really want is to have that beautiful Blue A100 color from the material palette as your background color.

Now please remove the actual view.background color line and remove the comment signs from the import mark 1 and the view.background color mark 2. The code will be broken because your project doesn’t have the MyColors framework dependency added, we will solve this problem soon but first, let me explain the 1 and 2 marks in the code.

The 1 mark is when I’m telling the code to import the dependency of the framework we’ll create. This is very important because, without him, the Swift compiler can’t tell that the extensions that will be used on the 2 mark exist. When we add that we are telling the compiler: “Swift bring me the UIKit module and the MyColors modules to this file”.

The 2 mark on the “view.backgroundColor = UIColor.Material.blueA100” is when we use the MyColors framework to get the Material color blue A100. I’m not telling that material colors are better than the UIColor default colors, it’s just an example.

 

How to create a Framework

Now it’s time to create the framework.

  1. Create a new framework press command+shift+n and select Framework.
  2. Name it MyColors.
  3. Create a swift file MainColors.swift.
  4. Add all the content of this repo to the file.

And your framework is done, just build it to generate inside the Products folder the MyColors.framework and we are ready to set up in the BundleForAllExample app.

 

Adding the framework to the app

Now you just need to drag the MyColors.framework of your framework project to the “Frameworks, Libraries and Embedded Content” of the BundleForAllExample app like the image below:

Frameworks: embed or not embed that's the question, dynamic and static libraries image 8

After you drag it into your app be aware if Xcode is set in the “Build Phases” tab of your Target the MyColors.framework. If not, you should just look up in your folders and link manually.

Troubleshooting tip: if your Xcode doesn’t collaborate linking automatically the framework, you can go to Build Settings -> Framework Search Paths, and there you put the exact path ( go to the left bar framework folder -> right-click on MyColors.framework -> show in finder -> get the path to it -> add the path to the Framework Search Paths)

Frameworks: embed or not embed that's the question, dynamic and static libraries image 9

Now back to the General tab, let’s see the options of embedding the framework.

Frameworks: embed or not embed that's the question, dynamic and static libraries image 10

And if you click on the right-side arrows, the options will appear:

Frameworks: embed or not embed that's the question, dynamic and static libraries image 11

This is how you can manipulate all the options that we discussed earlier.

Now go inside your framework and change the mach-o-type of it, you can choose between a static library or a dynamic library. In the same way, if you want to embed or not your framework in your final app bundle you can manipulate those options in General -> Frameworks, Libraries, and Embedded Content.

Finishing the App

Go back to the ViewController and make sure you add two things to it.

This:

import MyColors

And inside viewDidLoad() this:

view.backgroundColor = UIColor.Material.blueA100

Run your project, the blue should be the new material A100 blue. What a lovely day!

Frameworks: embed or not embed that's the question, dynamic and static libraries image 12

 

Sizes Comparison between IPA files

To finish this and wrap up all that we discussed I generated four .ipa archive files to demonstrate how different the size can be depending on what options you choose. I’ll sort in ascending order and I think you can imagine already what options will be the smallest and the biggest ones. I’ll use the archive process for the development team because it’s easier and it’s just to show the differences between sizes, for your environment you should check if you will need to sign or not in case of embedding content.

First, let’s see the smallest option with 33kb .ipa : Do Not Embed in App and Dynamic Library in framework mach-o-type options. This is obviously the smaller one because if you don’t embed a dynamic library, not a single line of code of the framework will be present in the final bundle, this means that if your app depends on this framework to run production code, it will crash.

Frameworks: embed or not embed that's the question, dynamic and static libraries image 13

The second one with 64kb .ipa is: Not Embed in the App and Static Library in framework mach-o-type options. This is also pretty straightforward by now: as the static library is statically linked to the main app code, the swift compiler can do some optimizations to compress the size of the framework inside the final app code.

Frameworks: embed or not embed that's the question, dynamic and static libraries image 14

The third .ipa file has 84kb and has the options: Embed in the App and Dynamic Library in framework mach-o-type. This will bundle the framework code into the final .ipa file but the symbols inside the main app code are external and available at run time through dynamic linking. The default behavior is to generate a folder called framework that your app can link in runtime the files.

guide to Frameworks: embed or not embed that's the question, dynamic and static libraries image 15

The fourth and it’s not a surprise with 371kb .ipa file is: Embed in the App and Static Library in framework mach-o-type. This archive in the .ipa will have the Framework folder with all the contents of the framework and also the main code will have all the code that the static library has. So this option is only useful if you need to get the media bundle inside the static framework, otherwise is a really bad idea.

Frameworks: embed or not embed that's the question, dynamic and static libraries image 16

 

Continue your iOS Architecture Studying

If you want to have a good grasp about what are the access level modifiers that are a key feature when using modules, you can check this article that says everything you need to know about encapsulating your objects inside your modules.

Another good thing to learn is the delegation pattern which is pretty common in iOS development to pass data between views.

 

Summary – Frameworks: embed or not embed

I hope you, my dear readers, enjoy this content as much as I enjoyed preparing and studying this. This is just an introductory topic on Frameworks and Xcode packing but it’s some foundation knowledge that I thought it would be great to share with you.

As always if you have any comments or feedback, please don’t hesitate to share. I want to know your impressions on this.

That’s all my people, I hope you liked reading this article as much as I enjoyed writing it. If you want to support this blog you can Buy Me a Coffee or leave a comment saying hello. You can also sponsor posts and I’m open to freelance writing! You can reach me on LinkedIn or Twitter and send me an e-mail through the contact page.

Thanks for reading and… That’s all folks.

Credits: image

Share this post:

Related posts

Sponsor