Creating a Framework for iOS

Learn how to build an iOS framework, which lets you share code between apps, modularize your code or distribute it as a third-party library. By Emad Ghorbaninia.

Leave a rating/review
Download materials
Save for later
Share
Update note: This tutorial was updated to iOS 14, Xcode 12 and Swift 5.3 by Emad Ghorbaninia. The original tutorial was written by Sam Davies.

Have you ever wanted to share a chunk of code between two of your apps or wanted to share a part of your program with other developers?

Maybe you wanted to modularize your code like the iOS SDK separates its API by functionality. Or perhaps you want to distribute your code the same way popular third party libraries do.

In this tutorial, you’ll extract CalendarControl, developed in Creating a Custom CalendarControl for iOS into a separate reusable framework. Along the way, you’ll:

  • Create a new framework for CalendarControl.
  • Migrate the existing code.
  • Import everything back to the app.
  • Build a binary framework, XCFramework.
  • Pack it as an uber-portable Swift Package.
  • Set up a repository for your Swift Package and publish it.

By the time you’re done, the app will behave as it did before while using the portable XCFramework you developed!

Getting Started

Download the starter and final projects by using the Download Materials button at the top or bottom of this tutorial. Find the starter project folder. Locate 1-RWCalendarPickerUI and open RWCalendarPicker.xcodeproj.

RWCalendarPicker is a Reminders-like checklist app that lets users create tasks and set their due dates.

Build and run to get an idea of how it works.

Showcase

Take a look at the files in RWCalendarPicker to familiarize yourself with the project. CalendarControl‘s code is split into several classes:

  • Day.swift: A data model which holds data of each day object.
  • MonthMetadata.swift: The data model for months.
  • CalendarDateCollectionViewCell.swift: Shows days in a month using cells in a collection view. Each cell is customized here.
  • CalendarPickerFooterView.swift: Lets the user select different months.
  • CalendarPickerHeaderView.swift: Shows the current month and year, lets the user close the picker and displays the weekday labels.
  • CalendarPickerViewController.swift: The body of the calendar where all related views are combined.

CalendarPicker is pretty handy. Wouldn’t it be nice to use it in several apps beyond this one? Frameworks to the rescue!

What is a Framework?

Frameworks are self-contained, reusable chunks of code and resources you can import into many apps. You can even share them across iOS, tvOS, watchOS and macOS apps. When combined with Swift’s access control, frameworks help define strong, testable interfaces between code modules.

Frameworks have three major purposes:

  • Encapsulate code
  • Modularize code
  • Reuse code

If you’ve programmed in other languages, you may have heard of node modules, packages, gems or jars. Frameworks are the equivalent of these in the Apple ecosystem. Some examples of common frameworks in the iOS SDK include Foundation, UIKit, SwiftUI, CloudKit and Combine.

In Swift parlance, a module is a compiled group of code distributed together. A framework is one type of module while an app is another.

Note: If you want to learn more about frameworks, read What are Frameworks?.

Creating a Framework

In Xcode 6, Apple introduced the Cocoa Touch Framework and recently changed it to Framework. Creating frameworks has never been easier. First, you’ll create the project for the framework.

In Xcode, select File ▸ New ▸ Project…. Then choose iOS ▸ Framework & Library ▸ Framework.

Framework selection dialog

Click Next. Then set the Product Name to CalendarControl. Use your own Organization Name and Organization Identifier.

Framework configuration dialog

Click Next. In the file chooser, choose to create the project at 2-Framework. Then click Create.

Now you have a project, albeit a boring one, that creates a framework!

Adding the Source Code to the Framework

Your current state is a framework without code. That’s about as appealing as straight chocolate without sugar. In this section, you’ll introduce code by adding the existing files to the framework.

From the RWCalendarPicker source directory, drag Day.swift into the CalendarControl project in Xcode. Make sure to check Copy items if needed so the files copy into the new project instead of adding a reference. Frameworks need their own code, not references, to be independent.

File into the framework

Double-check that Day.swift has Target Membership in CalendarControl to ensure it appears in the final framework. Verify this by selecting this file and ensuring CalendarControl is selected in the Target Membership area of the File inspector.

Now, add these files to your project by following the steps above:

  • MonthMetadata.swift
  • CalendarDateCollectionViewCell.swift
  • CalendarPickerFooterView.swift
  • CalendarPickerHeaderView.swift
  • CalendarPickerViewController.swift

Add all the classes

Note: Separating classes into their own folder group isn’t strictly necessary, but it’s good practice for organizing your code.

Select your project in the Project navigator and choose CalendarControl in Targets. Open the Build Settings. Then set Build Libraries for Distribution to yes. This produces a module interface file which shows your public API when someone jumps to definition of your module in Xcode.

Build Libraries for Distribution

Build the framework project. Make sure you get Build Succeeded with no build warnings or errors.

Adding Framework to the Project

Close CalendarControl. Go back to RWCalendarPicker. Now that you’ve assembled your calendar framework into the framework, you no longer need the migrated files in the main project. Delete the following files. Select Move to Trash in the confirmation dialog.

  • Day.swift
  • MonthMetadata.swift
  • CalendarDateCollectionViewCell.swift
  • CalendarPickerFooterView.swift
  • CalendarPickerHeaderView.swift
  • CalendarPickerViewController.swift

Remove classes

Build the project. You’ll see several predictable errors where Xcode complains about not knowing what the heck a CalendarPickerViewController is. Specifically, you’ll see a Cannot find ‘CalendarPickerViewController’ in scope error message.

You’ll solve these problems by adding the CalendarControl framework project.

Embedding Your Binary

Now, right-click the root RWCalendarPicker node in the Project navigator. Click Add Files to “RWCalendarPicker”.

In the file chooser, navigate to 2-Framework/CalendarControl and select CalendarControl.xcodeproj. Then click Add to add it as a sub-project.

Embedding

However, combining the projects makes it easier to develop the framework and app simultaneously. Any changes you make to the framework project automatically propagate up to the app. It also makes it easier for Xcode to resolve the paths and know when to rebuild the project.

Note: It isn’t strictly necessary to add the framework project to the app project. You could add the CalendarControl.framework output.

However, combining the projects makes it easier to develop the framework and app simultaneously. Any changes you make to the framework project automatically propagate up to the app. It also makes it easier for Xcode to resolve the paths and know when to rebuild the project.

Build and run. You’ll see the same compile error!

Error

Even though the two projects are now together, RWCalendarPicker still doesn’t get CalendarControl. It’s like they’re sitting in the same room, but RWCalendarPicker can’t see the new framework.

Follow these steps to fix the problem:

  1. Change the scheme to CalendarControl and build it.
  2. Then, expand the CalendarControl project to see the Products folder.
  3. Look for CalendarControl.framework beneath it. This file is the output of the framework project that packages the binary code, headers, resources and metadata.
  4. Then select the top level RWCalendarPicker node to open the project editor.
  5. Click the RWCalendarPicker target. Then go to the General tab.
  6. Scroll down to the Frameworks, Libraries and Embedded Content section.
  7. Drag CalendarControl.framework from the Products folder of CalendarControl.xcodeproj onto this section.

Add the Framework

You added an entry for the framework in Frameworks, Libraries and Embedded Content.

Now the app knows about the framework and where to find it. That should be enough, right?

Switch to RWCalendarPicker scheme and build the project. More of the same errors.

Still not working

You missed an important part of Framework development: Access Control.