Creating your first iOS Framework

If you’ve ever tried to create your own iOS framework, you know that it’s not for the faint of heart – managing dependencies and writing tests doesn’t make it any easier. This tutorial will walk you through creating your first iOS framework from start to finish so that you can go out and create your own.

We’re going to build a framework that exposes a function called RGBUIColor(red:green:blue) that returns a new UIColor created from those values. We’ll build it using Swift , with Carthage as our dependency manager. Our framework will be consumable using Carthage, CocoaPods, or git submodules.

Let’s begin!

Setting up the Xcode Project

Select File → New → Project .

Select iOS → Framework & Library from the left sidebar and select “Cocoa Touch Library” on the right.

Click “Next” and fill in the option prompts. Make sure to select the “Include Unit Tests” check box.

Select where you’d like to save your project.

Uncheck “Create Git repository on My Mac”, we’ll manually set it up later.

Click “Create” and the project will open in Xcode.

Go to File → Save As Workspace and save it in the same directory as your Xcode project with the same name. We put the project in a workspace because we’ll be adding our Carthage dependencies as submodules; they must be in a workspace for Xcode to build them.

In this script, we make sure the user has Carthage installed and run its update command to install the iOS dependencies.

We’re using --use-submodules so that our dependencies are added as submodules. This allows users to consume our framework outside of Carthage if they want. We use --no-use-binaries so that our dependencies are built on our system.

With bin/setup created, let’s run it so that Carthage will download our dependencies.

In the terminal, run bin/setup .

Now we need to set up our project to build and link the new dependencies.

Adding Dependencies to the Workspace

Since our dependencies are submodules, we need to add them to our workspace.

Open up Carthage/Checkouts and add each dependency’s .xcodeproj to the root of the workspace. They can be dragged from Finder into the navigator of the Xcode project.

When you’re done it should look like:

Link Runtime Dependencies

With “RGB” selected in the Navigator and the “RGB” target selected on the middle sidebar, select the “Build Phases” tab and expand the “Link binary with libraries” section.

Click the “+” icon and select the Curry.framework from the Curry-iOS target.

Click “Add”.

Link Development Dependencies

Select the “RGBTests” target from the middle sidebar.

Using the same process as before, add the Quick and Nimble frameworks to the “Link binary with libraries” section for this target.

When adding dependencies to each target, Xcode will automatically add them to the “Framework Search Paths” under the “Build Settings” tab. We can remove these from the “RGB” and “RGBTests” target because Xcode treats them as implicit dependencies due to them being in the same workspace.

Next, look in the “RGB” project in the Navigator; you’ll see there are three new frameworks at the root level. To keep this area organized, highlight all three, right click and select “New group from selection” to place them in a named group. I’ll call mine “Frameworks”.

Now that Carthage is set up, let’s add CocoaPods.

Adding CocoaPods support

To add CocoaPods support, we need to create a .podspec at the root of our project and fill in our project info.

One line to pay attention to is spec.dependency "Curry", '~> 1.4.0' . Because we’re supporting CocoaPods, we expect the consumers of our framework to be using it instead of Carthage, so we have to specify dependencies here and in the Cartfile .

Once this is set up we can run the pod lib lint command to test that everything is configured properly. If all goes well, we’ll see something like this:

With the project and dependencies set up, we’re almost ready to write some code. Before we do that, let’s create our first commit.

git commit -am "Project and dependencies set up"

Writing the First Test

Open RGBTests/RGBTests.swift so that we can take a look at the default template. It uses @testable and XCTest , but we’ll be changing both of these.

We’ll remove @testable because we want to test the public API that consumers of the framework will use. As our framework grows, we may need @testable to test parts that are not exposed publicly; generally we want to avoid that so we are testing what’s exposed to the consumer. This feature is most useful in testing applications rather than frameworks.

With testability, you are now able to write tests of Swift 2.0 frameworks and apps without having to make all of your internal routines public. Use @testable import {ModuleName} in your test source code to make all public and internal routines usable by XCTest targets, but not by other framework and app targets.

We’ll use Quick and Nimble for testing. Quick provides a nicer testing interface with a behavior-driven style that is very similar to RSpec and Specta; Nimble gives us many powerful assertions and the ability to write asynchronous code with less boilerplate.

We’re Green!

Let’s commit this bad boy.

git commit -am "Completed my first iOS framework!"

That’s all folks!

That’s it. There were a lot of steps but we’ve successfully created a marginally useful framework that could be published to GitHub. As a matter of fact, we published the source for this framework on GitHub .

We can’t wait to see what kinds of awesome open-source projects you’ll create.