Dependency/Package Manager
Most modern languages come with an official solution for code distribution. In today’s world of modern mobile development, it is essential to re-use the code already written by developers. Code reuse can be achieved by creating and distributing the packages from central repository. A package manager is a tool that simplifies the process of working with code from multiple sources. Typical Package Manager should have ability to do following things
- Centralised hosting of packages and source code with public server with access to developers or contributors
- Download the source code at the run time, so that we don’t need to include it in the repository.
- Link the source code to our working repository by including source files.
- Allow packages to be versioned
The examples of popular package managers are RubyGems for Ruby , Composer for PHP , NPM for NodeJS, CocoaPods for iOS
The basic usage of most package managers are mostly common,
- Define the file with all required dependencies (Gemfile, composer.json, package.json, Podfile).
- Download the dependencies with specific command ( gem/bundle install, composer install, npm install, pod install). This will create lock file with all the all the installed versions of the dependencies. e.g (Gemfile.lock, Composer.lock, Podfile.lock). This will also create a directory with downloaded source code at the specified location e.g (vendor/)
- Update the dependencies for new version ( gem/bundle update, composer update, npm update, pod update). This will update lock files with new version.
- Add required packaged by browsing packages on the hosting server.
The Swift dependency management for iOS does exactly same things but it has additional task of building the Xcode scheme. Apple has released it’s own package manager called Swift Package Manager to share and distribute Swift packages. It’s good to know that Apple is working on replacement of the current package managers in the iOS development world those are CocoaPods and Carthage. In this post we will cover popular Swift dependency managers. Those are CocoaPods, Carthage and Swift Package Manager. We will use SwiftyJSON which is very popular Swift library for parsing JSON as an example.
CocoaPods
CocoaPods comes as a Ruby library and need to be installed using RubyGem. CocoaPods is built with Ruby and is installable with the default Ruby available on OS X.
1 |
$ sudo gem install cocoapods |
CocoaPods can be initialised with pod init command which will create template Podfile but we can create our own simple Podfile will look like this
1 2 3 4 5 6 |
platform :ios, '8.0' use_frameworks! target 'MyApp' do pod 'SwiftyJSON', '~> 2.3' end |
Now, we can download dependency using magical command
1 |
$ pod install |
COCOPODS AND XCODE
The above command (pod install) is very magical which make lots of changes to our Xcode project under the hood. The most of the times, it’s really hard to understand that what has been changed. This might be the reason most developers hates CocoaPods. CocoaPods makes following changes to Xcode.
- .xcworkspace file ( Another file on top of .xcodeproj to open project)
- Podfile.lock (Locked versions of CocoaPods)
- Pods directory (Directory Containing source code of the Pod dependencies)
- Lots of things inside your Xcode Settings!
Now,we have to use .xcworkspace to open the project to import your dependencies otherwise CocoaPods won’t work.
COCOAPODS PROS AND CONS
The use of CocoaPods has following Pros and Cons
PROS
- Easy to setup and use.
- Automatically does all the Xcode setup for the project.
- Well grown community and support.It has the largest community and is officially supported by almost every open-source iOS library.
CONS
- It’s Ruby and we have to manage Ruby dependencies e.g Bundler, Gems etc etc
- CocoaPods updating Xcode Projects and Files is like magic without understanding what’s changed
- Centralised
- Can’t work with framework and project at the same time because of two-step process for working on dependencies.
Carthage
Carthage is another simple dependency manager for the Cocoa application. It downloads and build the dependencies but will not change Project file Or Xcode project build setting like CocoaPods. We have to manually drag . framework’ binaries to Linked Frameworks and Libraries .
We can install Carthage using HomeBrew
1 |
$ brew install carthage |
We are now ready to use Carthage. As above, we need to get SwiftyJSON using Carthage then we have create file called Cartfile with following content.
1 |
github "SwiftyJSON/SwiftyJSON" |
Now that, we have specified our dependency in the Cartfile, Run
1 |
$ carthage update |
This will fetch dependencies into a Carthage/Checkouts folder, then build each one. Now everything CocoaPods does automatically as magic, we have do it manually.
On your application targets General settings tab, in the Linked Frameworks and Libraries section, drag and drop each framework you want to use from the Carthage/Build folder on disk. There are also some workaround for the App Store Submission bug, which you can read on Carthage README file. After doing this all manual work, we should be able to import dependencies.
CARTHAGE AND XCODE
Carthage won’t touch Xcode settings or Project files. Carthage being very simple and just checkout and build the dependencies and leave it to you to add the binaries to Xcode. It gives you full control of what we are adding to Xcode.
CARTHAGE PROS AND CONS
There are some pros and cons of the Carthage
PROS
- Carthage won’t touch your Xcode settings or project files. It just download and build the dependencies so you have proper control on what you are doing.
- Decentralised
- Supports submodules
CONS
- Unstable and Slow
- Small Community, not many contributors
- Lot of manual steps to perform on Xcode to get everything setup
Carthage is very simple Swift dependency manager but it involves lot of manual setup.
Swift Package Manager
The Swift Package Manager is a tool for managing the distribution of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies.
Swift Package Manager is not only package manager but also Build and Test tool. Swift Package Manager can also run on Linux as well as macOS. Swift Package Manager is
- Command Line Based tool
- Being Cross-Platform, Swift Package Manager doesn’t need Xcode to create package
- It’s decentralised
- Swift Package Manager is open-source and source code is available on Github
Create Swift Package
It’s very easy to create our basic Swift package. Your default Hello World Package is ready to publish if you execute following commands.
1 2 3 4 5 6 |
$ mkdir Greeter $ cd Greeter $ swift --version $ swift package init --type=library $ swift build $ swift test |
At this stage, we should have default Hello World package ready to publish on Github. In order o publish package, we need to push it to GitHub account. Assuming we have git setup. Replace username and package name with yours. Swift packages uses semantic versioning to version packages.
1 2 3 4 5 6 |
$ git init $ git commit -am "Publishing Swift Package" $ git remote add origin git@github.com:YOUR_GITUSERNAME/PACKAGE_NAME.git $ git push origin master $ git tag v1.0.0 $ git push origin v1.0.0 |
We have published our first Swift Package. The published package can be found on Github here.
Generate Xcode Project
- Swift Package has command to generate Xcode project from the source code so that we can use Xcode for autocompletion etc etc
1$ swift package generate-xcodeproj
This will create xcproj file to open project in Xcode. -
Using Swift Packages
We can use existing Swift packages by creating package.swift file and specifying dependencies inside the file. This file should look like this
1 2 3 4 5 6 7 8 |
import PackageDescription let package = Package( name: "Greeter", dependencies: [ .Package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", majorVersion: 3, minor: 1) ] ) |
We will download the SwiftyJSON dependency using fetch command.
1 |
$ swift package fetch |
Now that, we should have SwiftyJSON dependencies checked out inside Packages directory. We can use that dependency now in our project using
1 |
import SwiftyJSON |
Swift Package Manager Pros and Cons
Swift package manager is very new tool and it has pros and cons
Pros
- Swift Package Manager is official Package Manager for Swift
- Managed by Apple
- Server side support
Cons
- Swift Package Manage is very new tool and undergoing lot of changes
- Swift Package Manager isn’t officially supported for all platforms.
- Swift Package Manager only work for other Swift package or project following Swift Package Manager’s directory standards.
Conclusion
It’s very challenging to select a Swift dependency manager for iOS project as all of the package managers has it’s own pros and cons. Swift Package Manager will be definitely replace CocoaPods and Carthage in the future but meanwhile we have to use CocoaPods or Carthage.