Creating an iOS Shared Library in an Easy Way

Reusing code is something developers pursue continuously. With it, we improve the quality of the product, as we reuse something that has been used and tested previously, and because of that we are confident on it. As all this logic is centralized, it is easier to maintain, both for applying any fix and for making any change about the features it implements. The scope in which we may apply code reuse is not restricted to the project itself. We can share code between different projects. In this way, we can create a common piece of code and use it for example in two different projects we are developing in parallel. Or even we can take it further, and create a library containing a set of common features that we think will be useful for future projects and use it in all of them. This will reduce the cost of these projects. This blog entry is about how to share code between different projects, in this case for iOS, though the idea may be extrapolated to other languages or technologies.

As in many other situations, there are many ways to get the code reuse we are looking for. For instance, a simple idea, though probably not the best one, would be to take advantage that we use Git as our version control tool. As we are using Git, we may include the shared library as a Git submodule. This means that we could place our common code in a separate Git repository and add a reference to it in every repository that would need it. This technique is very effective and easy to apply. However, the main disadvantage of this is that the reference to the code is a pointer to a specific Git commit of the shared library. This reference is not updated unless we manually do that. Also, it is not easy, unless we review the git history, to determine which version of the library we are using, as we reference to Git commits instead of using numeric versions of the release of the product.

In order to find out a better alternative, we have to see that this code, which we are sharing between both projects, is in fact a dependency of both of them. That is, we may see it as an external code that we need. In this way, we can introduce the shared library with Cocoa Pods, which is a dependency manager for iOS. We are used to work with Cocoa Pods to add third-party libraries by adding the definition of these dependencies in the Podfile. For example, it is quite common to include Alamofire as a library to manage HTTP requests by adding this to that file:

pod 'Alamofire', '~> 4.7'

As we see, the reference now is to a concrete version, in this case the release 4.7, and not a specific commit as we had before. In this way, it is easier to know which version are we using, find the documentation for it, and update it if we need to do so.

In the previous example, we are adding a public library. Cocoa Pods also lets you add private ones. For that, we simply need to configure to public the library pod to be deployed to a private repository which is only accesible to the people who need it. For the sake of simplicity, so that we do not have to get into the details of that configuration, we are going to opt for an alternative, which will let us have something similar to that private shared library. So the idea we will follow is to create a shared library and load it by specifying the relative path to the folder where it is located. In this way, our source control will determine the visibility of the library. However, we will have to downloaded and place it just where it is expected it to be. With this technique, although we are not linking to a specific version of the shared library we are sure that we will be using the code which has been placed in that folder. So, we can use continuous integration tools or scripts, to automate the download of the shared library to the version we need. For instance, to the latest code in the stable branch or to a specific release tag. We could even use that as a step for the distribution of apps with Bitrise.

Creating the Library Step by Step.

First, we need to install Cocoa Pods if we have not already done so. The easiest way to achieve that is by using the Ruby gem, by executing this line of code.

sudo gem install cocoapods

Once it is installed we will have the command “pod” in the terminal. We can create a project called “shared_lib” by executing:

pod lib create shared_lib

This will trigger the process to create the library. We will be asked some questions regarding the library, such as the platform the library is for (iOS or macOS) or the language we want to use (Objective-C or Swift). Once we are done with this, the library will be created and automatically opened in Xcode. Because of the command we have used to create the library, we will have applied the default template for the library. This means that this project will have a very characteristic structure. The documentation of Cocoa Pods explains it in detail. For this example, we will just go to Pods/Development Pods/shared_lib  and we will see a class called ReplaceMe.Swift. We can create a new class there called MyLibrary.swift and delete ReplaceMe.Swift. Note that the logical structure of the project is different from the structure of folders, and that class is located in the path shared_lib/Classes. In the class we have just created, we can add the following piece of code, which we will use to test our approach.

public class MyLibrary {

    public init() {
    }

    public func sayHi() {
        print("Hi from the shared library!");
    }

}

Now, we are going to use that function from a different project. For that, we will create a new project where we will add the call to the function. We will create the project as usual, from Xcode (File / New Project) and we will create it in the same path as the shared library root folder is. That is, if we call the new project MyProject, the folders “MyProject” and “shared_lib” will be in the same folder, having a structure like this one:

+ MyProject

    - MyProject

    - MyProject.xcodeproj

    - MyProjectTests

+ shared_lib

From the terminal, we will get into the folder of the project (MyProject), so we will be in the same path as where MyProject.xcodeproj is located. There we will initiate the integration with Cocoa Pods for the project:

pod init

This will create a file called Podfile, in which we can add the dependencies of the project. We have to open and edit it to add the dependency for the shared library and indicate the target of the project. We can set the target by simply uncommenting the line where it says

platform :ios, '9.0'

This will set iOS 9 as the target of the project. For the shared library we will have to add the relative path to the folder where it is located:

# Pods for MyProject

pod 'shared_lib', :path => '../shared_lib'

Now, we will execute in the terminal pod install to install the dependencies. This will create a MyProject.xcworkspace, which we will open, and we will see that we have our project and the associated dependencies.

In this project now we can use the class of the shared library. We just need to import the pod and we will see the public classes and public methods of it. For example we can add this to the app delegate class:

import shared_lib

...

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    // Override point for customization after application launch.

    MyLibrary().sayHi();

    return true;
}

If we review what we have done, we have run pod installwhen we have added the dependency for the first time. It is important to know that once it has been added and the code of it changes, we have to execute pod update to bring the changes to the project that is using the dependency.

Conclusions

We have seen a quite simple way to share code between different iOS projects. The idea is simple, as it is just loading the library from a relative path to the project. We can start with this and iterate on it, deploying it to a public repository, or configuring our own private repository to be used internally in our organization. In any case, this approach is nos specific to iOS. So it could be used for instance in Android creating a library and loading it with Gradle, or in Node by using npm. In this way, we will be able to reduce the development time of the projects and improve the quality of our code.

Leave a Comment

Responsable » Solidgear.
Finalidad » Gestionar los comentarios.
Legitimación » Tu consentimiento.
Destinatarios » Los datos que me facilitas estarán ubicados en los servidores SolidgearGroup dentro de la UE.
Derechos » Podrás ejercer tus derechos, entre otros, a acceder, rectificar, limitar y suprimir tus datos.

By completing the form you agree to the Privacy Policy

¿Necesitas una estimación?

Calcula ahora