iOS Programming Recipe 34 – Making Your Own Cocoapod

In ruby on rails, which is an open source web framework, there exists a nice system of libraries called “Gems” that can be easily imported into a web project and just used. These gems also have a versioning system, that allows the developer to pick a specific version for the project, or more importantly keep the version consistant so the project doesn’t break because of a future change. Cocoapods gives the iOS developer this same kind of power. With cocoapods you can not only take advantage of thousands of open source libraries, but you can also make your own pods to keep track of several versions of libraries you make yourself. Currently, Apple doesn’t have a good versioning system solution. The community responded with Cocoapods, and today we’re gonna explain what a cocoapod is an how to make your own.

Assumptions

  • You are familiar with the command line interface and creating Xcode projects.
  • You have are fairly comfortable with git and creating tags
  • You’ll need to install cocoapods on your system for this tutorial, so go here and follow the instructions to install it. You will need to type these commands in your terminal.
  • You’ll want to setup a github account and generate an SSH key, Do that here and here.

What is a Cocoapod?

At the heart, Cocoapods are essentially a system for managing git repos. Under the hood they basically check for git tags and choose the correct git tag for the version specified and checkout that branch. They also make sure all the dependencies needed are also added to the project with their correct versions.

For a good example. Say you had a library that downloads images and gives them photo filtering. For this you may want a pod for image manipulation (Say GPUImage) and a pod for downloading images (say AFNetworking). Now your library would have two dependencies, GPUImage and AFNetworking. Cocoapods will make sure these two libraries are also included with whatever version you specify.

Now imagine you create a new project and you want to use the same library, but you need to modify the library to allow zooming. Well then you would create a new version of the cocoapod and your past projects wont be affected by the new changes as long as they are using the correct version.

Now that we’ve painted a picture of just how useful cocoapods can be, lets start by first using a Cocoapod. We’ve done this several times on NSCookbook, but we’ll do it again just to consolidate the info in one place.

Setting up a project with Cocoapods

Start by creating a new single view controller project in Xcode called NSCButton. One thing that I find myself frequently doing is creating custom buttons, So let’s make a simple library for that. While we’ll be creating a library, we’ll want to create a project to build our library in. Later we’ll just need a few files from the project.

Once you have created the new single view controller application, close Xcode and open the terminal.

On the command line type the following in the command line


cd Desktop/NSCButton  <- press enter when done
pod init <- press enter when done

So this navigated us to our project folder and created a podfile. A podfile will be where we specify our dependencies for this project.

Now in the finder, navigate to the project folder and open the newly created podfile. If you are familiar with VIM or have a command line text editor you can open it directly from the terminal. I have sublime, so I can simply type “subl podfile” in the command line and it will open the file in the Sublime text editor. When you open up your podfile it should look like Code Chunk 1.

Code Chunk 1


# Uncomment this line to define a global platform for your project
# platform :ios, "6.0"

target "NSCButton" do

end

target "NSCButtonTests" do

end

So, one pod I’ve found handy for making flat styled buttons is FlatUIKit, so let’s go ahead and add the pod to the list. Code Chunk 2 shows this update.


# Uncomment this line to define a global platform for your project
# platform :ios, "6.0"

target "NSCButton" do

pod 'FlatUIKit'

end

target "NSCButtonTests" do

end

Note: If you want the latest pod, then you can simply put the file as pod ‘podname’ . But, for this tutorial the latest version is 1.4, so you should probably include the version to insure no hiccups with iOS 7. In you’re file include pod ‘FlatUIKit’, ‘~> 1.4’ .

Now in the terminal you’ll want to type the following command:


pod install <- press enter when done

This will download the pod to your project and make an Xcode workspace. From now on , you’ll open the workspace file instead of the project file. so open NSCButton.xcworkspace. If you’ve done everything right, your project navigator should look like Image 1.

Image1

Image 1 : The project navigator with Cocoapods incorporated

Creating the Library

Ok, now that your project is setup, let’s start by actually creating something useful.

Create a new class with a UIButton as a subclass. Title the new class “NSCButton”.

Code Chunk 3 shows the header and implementation for this new class. We won’t get into detail , but it basically pairs all of the available colors in the FlatUIKit with their compliments for the shadows and automatically creates corner radius’ and such.

Code Chunk 3 The NSCButton class interface and implementation

.h file:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#import <UIKit/UIKit.h>
#import <FUIButton.h>

typedef NS_ENUM(NSInteger, NSCButtonBaseColor){

    NSCButtonBaseColorTurquoise,
    NSCButtonBaseColorEmerald,
    NSCButtonBaseColorPeterRiver,
    NSCButtonBaseColorAmethyst,
    NSCButtonBaseColorWetAsphalt,
    NSCButtonBaseColorSunFlower,
    NSCButtonBaseColorCarrot,
    NSCButtonBaseColorAlizarin,
    NSCButtonBaseColorClouds,
    NSCButtonBaseColorConcrete,
};

@interface NSCButton : FUIButton

- (id)initWithFrame:(CGRect)frame andColor:(NSCButtonBaseColor)inBaseColor;


@end

.m file:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
@implementation NSCButton

- (id)initWithFrame:(CGRect)frame andColor:(NSCButtonBaseColor)inBaseColor
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        [self setupButtonWithColor:inBaseColor];
    }
    return self;
}
- (void)setupButtonWithColor:(NSCButtonBaseColor)inBaseColor{

    self.shadowHeight = 3.0f;
    self.cornerRadius = 6.0f;
    self.titleLabel.font = [UIFont boldFlatFontOfSize:16];


    switch (inBaseColor) {
        case NSCButtonBaseColorTurquoise:
            self.buttonColor = [UIColor turquoiseColor];
            self.shadowColor = [UIColor greenSeaColor];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateNormal];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateHighlighted];
            break;
        case NSCButtonBaseColorEmerald:
            self.buttonColor = [UIColor emerlandColor];
            self.shadowColor = [UIColor nephritisColor];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateNormal];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateHighlighted];
            break;
        case NSCButtonBaseColorPeterRiver:
            self.buttonColor = [UIColor peterRiverColor];
            self.shadowColor = [UIColor belizeHoleColor];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateNormal];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateHighlighted];
            break;
        case NSCButtonBaseColorAmethyst:
            self.buttonColor = [UIColor amethystColor];
            self.shadowColor = [UIColor wisteriaColor];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateNormal];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateHighlighted];
            break;
        case NSCButtonBaseColorWetAsphalt:
            self.buttonColor = [UIColor wetAsphaltColor];
            self.shadowColor = [UIColor midnightBlueColor];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateNormal];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateHighlighted];
            break;
        case NSCButtonBaseColorSunFlower:
            self.buttonColor = [UIColor sunflowerColor];
            self.shadowColor = [UIColor orangeColor];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateNormal];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateHighlighted];
            break;
        case NSCButtonBaseColorCarrot:
            self.buttonColor = [UIColor carrotColor];
            self.shadowColor = [UIColor pumpkinColor];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateNormal];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateHighlighted];
            break;
        case NSCButtonBaseColorAlizarin:
            self.buttonColor = [UIColor alizarinColor];
            self.shadowColor = [UIColor pomegranateColor];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateNormal];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateHighlighted];
            break;
        case NSCButtonBaseColorClouds:
            self.buttonColor = [UIColor cloudsColor];
            self.shadowColor = [UIColor silverColor];
            [self setTitleColor:[UIColor silverColor] forState:UIControlStateNormal];
            [self setTitleColor:[UIColor silverColor] forState:UIControlStateHighlighted];
            break;
        case NSCButtonBaseColorConcrete:
            self.buttonColor = [UIColor concreteColor];
            self.shadowColor = [UIColor asbestosColor];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateNormal];
            [self setTitleColor:[UIColor cloudsColor] forState:UIControlStateHighlighted];
            break;

        default:
            break;
    }
}
@end

Go ahead and test the class by adding the Code Chunk 4 to the NSCViewController class in the viewDidLoad method.

Code Chunk 4: Using the class in the single view controller


1
2
3
4
5
6
7
8
- (void)viewDidLoad
{
    [super viewDidLoad];

    NSCButton *tmpButton = [[NSCButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2 - 50,self.view.frame.size.height/2,100,50) andColor:NSCButtonBaseColorSunFlower];
    [tmpButton setTitle:@"A Button" forState:UIControlStateNormal];
    [self.view addSubview:tmpButton];
}

Now if you run the project, Image 2 shows what this class does for us.

Image2

Image 2 : the NSCButton class in action

With our class complete we can now move into making this an actual Cocoapod.

Making the Cocoapod

The only files we really need for our cocoapod are the NSCButton.h and NSCButton.m files. The rest of it is unimportant to anyone wanting to use this as a library. So navigate to the project folder and find the two files and copy them into their own folder. Again, make this folder on the desktop and title it “NSCButtonPod”.

Now that you have a folder with the two files for the NSCButton class in it, you are ready to create a podspec.

Open up the terminal and type in the following commands:


cd /Desktop/NSCButtonPod  <- Press enter when finished
pod spec create NSCButton <- Press enter when finished

These commands navigated you to the NSCButtonPod folder and created a podspec file. Now you can open this file using your favorite text editor and start editing it. When you have it open, it should look like Code Chunk 5

Code Chunk 5 : An excerpt of the full Cocoapods file


#  Be sure to run `pod spec lint NSCButton.podspec' to ensure this is a
#  valid spec and to remove all comments including this before submitting the spec.
#
#  To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html
#  To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
#

Pod::Spec.new do |s|

  # ―――  Spec Metadata  ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #


  ...


   # s.requires_arc = true

  # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }
  # s.dependency "JSONKit", "~> 1.4"

end

Now this file has a bunch of different options depending on how you would like to set up your project, but I have narrowed it down to a few items that are important for this tutorial. Code Chunk 6 shows the podspec as it pertains to this tutorial.

Code Chunk 6: The podspec you’ll make


Pod::Spec.new do |s|

  # ―――  Spec Metadata  ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #

  s.name         = "NSCButton"
  s.version      = "0.0.1"
  s.summary      = "Takes FlatUIKit and adds sets up a button with contrast colors."

  s.description  = &lt;&lt;-DESC
                   A longer description of NSCButton in Markdown format.

                   * I wrote this to show people how ot make one of these
                   DESC

  s.homepage     = "http://www.nscookbook.com"
  s.license      = { :type =&gt; 'MIT', :file =&gt;'LICENSE.txt' }

  # ――― Author Metadata  ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
  s.author             = { "Joseph Hoffman" =&gt; "NSCookbook@gmail.com" }

  # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #

  s.platform     = :ios, "7.0"

  # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #

  s.source       = { :git =&gt; "git@github.com:NSCookbook/NSCButton.git", :tag => "0.0.1" } <- Replace with your source code


  # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #

  s.source_files  = "*.{h,m}"

  # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #


  s .requires_arc = true
  s.dependency "FlatUIKit", "~> 1.4"

end

Obviously you’ll want to update this file with your own settings. You’ll need to create your own github account and create a repo for the Source location for instance. You can get started with that here.

One piece of particular note in Code Chunk 6 is the s.dependency line. This makes sure that when we install the Cocoapod, that the FlatUIKit with version 1.4 also gets installed.

Once you have the podspec all setup, go back to the command line (Hopefully you haven’t closed it) and type the following from the folder you navigated to before:


git init
git remote add origin <your git repo (use SSH preferably)>
git add --all
git commit -m "First Commit"
git tag '0.0.1'
git push origin --tags

This will setup the git repo with the new files and the podspec. The important piece here is the tag we created. This is necessary for cocoapods to manage the dependencies.

Now there’s only one more step, and that’s to verify the podspec. Before we do that though, we need to add a new file in the repo called LICENSE.text. This is a requirement in order for the podfile to be correct. You can add whtever license you want, but here I have added an MIT license, so the text of the LICENSE.text file should contain the full MIT License statement. Once you have added the file, you can check it in to the repo with the following commands in the terminal:


git add --all
git commit -m "Added license File"
git push origin

To verify the podspec type the following command in the terminal:


pod spec lint NSCButton.podspec

Once this is complete, you’ll know it worked when the terminal prints to the screen “NSCButton.podspec passed validation.” Now you are ready to actually use the Cocoapod. First, you’ll need to decide whether or not to make the Cocoapod private or public.

Making your Cocoapod Public

We’ll start with the easy case, First you need to update the podspec so it uses the https source

So for my example spec.source now becomes:


  spec.source       =  :git => 'https://github.com/NSCookbook/NSCButton.git', :tag => '0.0.1'

Then run


pod spec lint NSCButton.podspec

To validate it.

and finally run


pod trunk push NAME.podspec

To submit to the CocoaPods Master repo.

Making your Cocoapod private

To make cocoapods private, you’ll need to setup a private repository. So go to github and create a new repo. I named mine “podRepo”. Then type in the following commands in the terminal to setup the new repo:


mkdir ~/Documents/podRepo
touch README.md
git init
git add README.md
git commit -m "initial commit"
git rmeote add origin <your git url (use the SSH one prefereably)>
git push -u origin master

Now that you have setup the repo, you simply need to add the repo to your cocoapods installation. so type the following in your terminal:


pod repo add podRepo <your git url>

now navigate to the pods folder to see if it worked:


cd /.cocoapods/repos/podRepo
pod repo lint .

if all went well, you should be able to navigate to the folder and it should tell you the podspec passed validation.

Now we simply need ot add the podspec to the newly created repo. So navigate to the place you hav your repo in by typing the following commands:

cd ~/Desktop/NSCButton

and then add it to your cocoapods by typing the next command:


pod repo push podReop NSCButton.podspec

Using your Cocoapod

The rest of this tutorial will be very familiar. As you did in the first part of this recipe, create a new single view controller project. and name it whatever you want. use the terminal to navigate to the new project folder and again type ‘pod init’.

Once you have created the new Podfile open it and instead of adding the FlatUIKit pod, we’ll add our own. so add the following line to your podfile:


pod 'NSCButton'

Then from the terminal inside of the project folder type the following command to install the pods:


pod install

If all went well, you’ll see the following output:


Installing FlatUIKit (1.4)
Installing NSCButton (0.0.1)
Generating Pods project
Integrating client project

[!] From now on use `<Your Project Name.xcworkspace`.

Now open up the the .xcworkspace file, and update the viewDidLoad method of your the single view controller with the code in Code Chunk 4. If you did everything right, it should look exactly the same as it did before.

Summing up

I know it seems like a lot of steps to make your own Cocoapod, but if it’s a piece of code or library that you will use often in your development, the work is really worth the effort.

Further Reading

If you are interested in learning more about how Cocoapods are used. Check out this short article I posted on the Fuzz Website, The company I currently work for.

About Joe Hoffman

I am An Electrical Engineer that spends a lot of my off time doing web development and other programming. Currently I am trying to expand my knowledge with iOS and I find that writing tutorials helps me learn more thoroughly as well as provide some useful info to others.

Trackbacks

  1. […] iOS Programming Recipe – Making Your Own CocoaPod […]

Speak Your Mind

*

css.php
Privacy Policy