19 August 2020

Creating a Binary Framework in iOS with Swift

We all use a lot of frameworks in our daily development routine. We just type the magical word “import” and it’s all set. But what’s happening behind that import statement? How do you make it possible for your fellow developers to use your classes with just one line of code? Today, I’ll try to show you how to create a binary framework.

First, it’s better to understand the difference between framework and library, a subject that we commonly come across in iOS developer interviews.

  • Library is a file that defines bunch of code; not part of your original target. A library can be dynamic (.dylib) or static (.a)

As you can understand from their names, static libraries are compiled once since the file size can be bigger.

Dynamic libraries, on the other hand, are loaded into memory when they are needed. This can be loadtime or runtime. All Apple system libraries are dynamic.

  • A framework is a package that contains resources like dynamic libraries, images, interface builder files, headers etc. It is basically a bundle that ends with .framework extension.

We will cover frameworks in this article.


Let’s dive into Xcode and see how to create one.

First, we need to choose Xcode -> New project -> Framework.

In this demo, we name our project VfkFrameworkDemo. It will be the name of our framework, too.

After creating a new framework project, all we see in our bundle is a single .h file.

We can leave that .h file as it is, we won’t be needing it later.

Let’s create a new swift file named, VfkFrameworkLogger.swift (filename doesn’t matter really) and add the code below.

import Foundation

public class VfkFrameworkDemo {

    public init() {
        debugPrint("VfkFrameworkDemo initialized.")
    }
}

Important side note:

Classes and functions which will be used in integration must be marked as public.

You can still keep your internal classes; they won’t be available to the developer who uses your framework.

That’s the beauty of binary frameworks; people can use your code in background, but they can’t see what you don’t want them to see. Privacy matters.

If we select “Generic iOS Device” from device list and build project, we see a file named VfkFrameworkDemo.framework in Bundle, under Products folder.

This is our first framework, now we can use it with drag and drop.

Well, that was simple. Are we done? Not quite.

The first problem we’ll encounter here is “targets.” We built our framework for “Generic iOS Device”, which means our framework can only be used on real devices.

That’s a bummer. A lot of iOS developers use simulators. What should we do?

Let’s change our target to “iPhone 8 simulator” and build again.

We did it, and now our framework can be used on a simulator. But wait…

We still need “real devices”, too.

Fortunately, there is a way to combine these two frameworks and create a universal one which will work both on device and simulator.

This workaround is generally referred as “aggregate target” and it’s a simple way to create universal framework in Xcode, without the need of using Terminal. (We can still use terminal for this process btw.)

Let’s create a new target with File -> New -> Target -> Aggregate.

For the sake of understanding this process, we name our new target “Aggregate”.

After creating our new target, we need to switch to “Aggregate”, so go to “Build Phases”, and create a new “Run Script”.

This is the code snippet we’ll use in the script.

UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal

# Make sure the output directory exists

mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"

# Step 2. Copy the framework structure (from iphoneos build) to the universal folder

cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/VfkFrameworkDemo.framework" "${UNIVERSAL_OUTPUTFOLDER}/"

# Step 3. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory

cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/VfkFrameworkDemo.framework/Modules/VfkFrameworkDemo.swiftmodule/." "${UNIVERSAL_OUTPUTFOLDER}/VfkFrameworkDemo.framework/Modules/VfkFrameworkDemo.swiftmodule"

# Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory

lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/VfkFrameworkDemo.framework/VfkFrameworkDemo" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/VfkFrameworkDemo.framework/VfkFrameworkDemo" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/VfkFrameworkDemo.framework/VfkFrameworkDemo"


# Step 5. Convenience step to open the project's directory in Finder

open "${UNIVERSAL_OUTPUTFOLDER}"

The process is simply explained in five steps.

First, we need to build our framework for both real device and simulator separately. After that, the run script will combine these two frameworks into one universal framework to rule them all.

  • Choose VfkFrameworkDemo -> Generic iOS Device and build.
  • Choose VfkFrameworkDemo -> iPhone 8 and build again.
  • Choose Aggregate -> Generic iOS Device and build again.

After these steps, Xcode (the run script) opens the finder and shows us our universal framework. This file can be used on both simulator and real devices.

Drag it into Desktop, we’ll use it in a couple of minutes.


Create a new Single-View Xcode project. We don’t need anything special. We just need a clean project to import our framework into.

  • Drag VfkFrameworkDemo.framework into the bundle.
  • Go to project’s General settings, select Embed & Sign from Frameworks, Libraries and Embedded Content menu.

This step is not important at this time, but it must be done to use the framework on a real device.

P.S. If you distribute your framework with Cocoapods, it takes care of that signing issue on its own.

This is what our new project looks like.

Open ViewController.swift and import VfkFrameworkDemo

Add the framework’s in it code into ViewDidLoad.

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        _ = VfkFrameworkDemo.init()
    }

This is our ViewController.swift file. Now Build and Run the project and have a look at debug console.

It worked! We just initialized our framework and used it from another project.

We didn’t see the framework’s code. We don’t know what happened in the background. With just a single line of code, the framework did its job −in this case, just a debug print− but it can be much more.

The ABI Stability came with Swift 5.1. That means a binary framework built with Xcode 10.2 or later can now be used on other Swift versions, too. Before that, a framework developer needed to build a new version of a framework for every Swift version. That was a real struggle but now it’s gone, kudos to Apple.

When creating VerifyKit, our development team came across with a strange bug. We can address this as “The corrupted .swiftinterface bug”.

We could use our framework on Macbook which built the .framework file without an issue, but when other developer tried to use it on another computer, Xcode gave the error “Failed to load module VfkFrameworkDemo”. (In our case, module name was VerifyKit)

We realized that Xcode created a corrupted .swiftinterface file and added our module name before every public class.

To fix this, you need to go framework’s folder in Terminal and run this line of code.

find . -name "*.swiftinterface" -exec sed -i -e
's/VfkFrameworkDemo\.//g' {} \;

This code snippet removes redundant module names (you need to replace VfkFrameworkDemo with your framework module name) in public class definitions, so everyone can use your framework.

I don’t know if this is a common bug, but it gave us a real headache, so I wanted to add this as a side note.

That’s it. We just created a universal binary framework in Swift and used it from another project.

We did it with the classic drag&drop, but there are other ways to distribute your framework, like Cocoapods or Carthage.

As you know, most common way to distribute your framework is Cocoapods. But unfortunately, it’s a subject for another article.

Please feel free to comment if you have any questions.

Don’t forget to check VerifyKit out!

Happy coding.

This article was written by Alper Kayabaşı, iOS Developer of VerifyKit

Most Viewed Posts

18 September 2020

What is the Best Phone Number Verification Method for Your Users?

SMS provides a secure way to authenticate users during phone number verification, but it’s not your only option. This article explains. Phone numbers offer the benefit of being unique; every mobile phone owner is assigned a different number. Stealing someone’s phone number or obtaining...

1 April 2021

4 Tips for Better Mobile App Security

The number of mobile apps is growing daily, and the issues of mobile app security and privacy continue to intensify as a result. Security professionals are growing more and more worried that common web app security practices aren’t cutting it anymore. While security professionals are busy...

24 February 2021

Going global: the challenges of app localization

You have your app up and running and it’s ready for prime time on the app stores. It can be downloaded and enjoyed by billions of people around the world, as app stores are global marketplaces for apps. Technically, yes, that is true. App stores are a great way to reach global audiences, but...

7 June 2021

The story of VerifyKit

Every brand has an origin story. Ours is one of dedication and hard work, how we developed VerifyKit and nurtured it to the global brand that it is today. In a nutshell, it’s the story of challenging ourselves at every corner, finding our own solutions to the problems we face, and sharing...

16 March 2021

4 mobile app development tips for start-ups

Say you have a brilliant start-up idea and you need a killer app to go with it. If you’re just beginning to set sail on your app development journey, it might get a little difficult navigating the waters of app development. We put together several app development tips for start-ups in this blog...

25 September 2020

How to Cut User Verification Costs

User verification is a must to ensure your app attracts genuine users – but it comes at a cost. Learn how to cut verification costs below.  Account security – how to keep users safe from scammers and hackers – is a leading priority for app developers. For that reason, user...

4 September 2020

Why Phone Number Verification is Crucial for Account Security

Security is a top reason as to why app developers are turning to phone number verification to authenticate users. This article explains. A big concern for app developers is account security; how to verify that users are genuine human beings and not scammers or hackers. Email verification...

18 January 2021

5 Tips for Developers Who Are on the Road to Success

The field of software development is extremely diverse and it continues to grow every year. More and more people are entering the industry every day and there are many different ways of doing it. Some choose to go to college/university to pursue a degree, some go to coding boot camps for a crash...

13 November 2020

What is Mobile Identity?

It’s said that more people today own a mobile device than a toothbrush. Whether you find this horrifying or a simple fun fact is up to you, but you can’t deny the reality: the world is moving away from desktop and laptop computing to mobile, and the challenges of identification and...