Apple may not like the fact that iOS developers adding the third-party dependencies to the iOS projects. Apple’s core technologies have provided enough frameworks and tools with healthy documentation that developers can use to build and distribute iOS apps. This might be the reason the Apple didn’t have any official package manager to manage dependency for iOS apps yet. However, this is not the reality, iOS developer wants to share and distribute code for reusability, avoid duplication and save time.
CocoaPods has been serving as a dependency management solution for iOS apps since long. It’s written in Ruby and iOS developers need to know Ruby in order to use it. As long as it works everything is OK but pain starts if something breaks in CocoaPods or the magical settings that CocoaPods has done inside Xcode project. Carthage is another dependency management solution which is written in Swift and maintained by Github engineers. In my last blog post, I have explained what’s the difference between CocoaPods and Carthage and how to choose a right framework. I would strongly recommend reading that post here to understand the basic difference. In this post, we will assume that you have decided to go to Carthage and we will see how easy it is to migrate from CocoaPods to Carthage. It can be easily achieved by applying these five steps.
- Dependency Analysis
- Carthage Dry Run
- CocoPods Decommissioning
- Cleaning Xcode Project
- Linking Frameworks to the targets
We will discuss each phase in details. One thing to note here, we are only talking about the Swift frameworks and dynamic libraries, not about the old Objective-C or static frameworks.
1. Dependency Analysis
The first step to migrate the iOS project to Carthage is dependency analysis. If you are using CocoaPods then there must be a list of dependencies hanging there inside the Podfile of the iOS project. In the analysis phase, you should so two major things.
Ditch Unwanted Dependencies
At this stage, try to get rid of the dependencies that you no longer using or can be replaced with another approach if possible. The example would be SwiftLint, think why do we need to add SwiftLint as the dependency to iOS app. It can be easily run on Github pre-commit hook or from command line script on the local machine or Continuous Integration server. Similarly, check how much other dependencies are being used and see if those can easily be replaced by native Apple technologies e.g Alamofire Or SwiftyJSON can be replaced by URLSession and Codable. Fewer dependencies less hassle.
Check Carthage Support
Almost all the major third-party Swift framework supports Carthage. The way to check that is to visit the Github repo page of the framework and look at the README file. There should be badge stating the Carthage support as well the platform support as shown below (not that big though)
If you don’t see the badge there and it’s Swift framework that can be built using xcodebuild and have scheme supported with iOS platform then that should be OK as well. Once, you confirmed these both things you can go ahead and run next step which is Carthage dry run.
2.Carthage Dry Run
At this stage, you have confirmed that dependencies that you need to migrate from CocoaPods to Carthage have been supported. It’s time to prepare the Cartfile and add all the dependencies there with correct versions mentioned either in the Podfile or Podfile.lockOnce Cartfile is prepared than try running the Carthage update on the current project.
$ carthage update --platform iOS
After this command, it might be time for coffee break. When you return from coffee break and everything has been successfully built then you are good to go to next step. However, you are stuck with errors it’s good time to fix those errors. The common errors are
- Swift version might different
- The framework not supports iOS platform or doesn’t build with Carthage in mind.
- Or any other error that has been specified by Carthage
Once everything is successfully built you should have Carthage directory with Checkout and Build subdirectories having all the source code of the dependency frameworks and pre-built frameworks. At this stage, you are good to ditch the CocoaPods from your iOS project.
When you have integrated CocoaPods in your iOS project, you might have observed that CocoaPods almost invaded your Xcode project. CococPods not only created Xcode Workspace but also penetrated deep into build settings and build phases. The process of removing all the mess from iOS project sounds like yak shaving but it’s not. There is no need to manually delete the CococPods files, scripts and frameworks. Big thanks to CocoPods-Deintegrate plugin that almost remove all marks that CocoaPods put inside Xcode project. We just need to download the plugin and run the pod deintegrate script from the root of the iOS project or where your Xcode project or workspace is located.
$ [sudo] gem install cocoapods-deintegrate
$ pod deintegrate
There is no need to reinvent the wheel as long this script works but it’s important to understand what this script is doing under the hood. In Summary, this script does following things
- Delete CocoaPods specific scripts from the build phases of each target. The scripts are usually “Copy Pod Resources”, “Check Pod Manifest.lock” and “Embed Pods Frameworks”.
- Remove Pod Libraries from the build phases libPods-.a
- Delete Pod file references from the project including .a file as well as all the .xcconfig files for al the targets
- Delete Pod groups from Xcode project
If you know Ruby then feel free to have a look at this deintegrator.rb file on Github Or you can write your own scripts in bash or python to remove above things. Again we can do the above steps manually as well but the automated way mentioned above will save your day for sure.
4. Clean Xcode Project
As you have seen above that we have almost removed the references of the CocoaPods in the previous step but there are still some CocoPods marks in our Xcode projects that we need to remove manually. The CocoPods-Deintegrate plugin doesn’t remove following things
- Xcode Workspace
- Podfile and Podfile.lock file
- The values attached to build configurations like COCOAPODS=1
We have to delete those things manually or using some scripts. There is another plugin cocoapods-clean to do remove workspace and Podfile but its very easy to delete it manually. You can also cross verify the Xcode project to see if there are any custom settings left behind.
Once you done with above steps, you are completely CocoPods free. You have successfully removed the white elephant from your iOS project. Yay!
5. Link Frameworks to Targets
This is the last step of the migration from CocoaPods to Carthage. At this point, you might have Carthage/Checkout directory with the source code of the dependencies and Carthage/Build directory with all the built .framework bundles. Now that, we have to link all these frameworks to the respective targets as mentioned in the Carthage documentation here. This is a bit of manual process but we have to do it only once. However, this gives you full control of the dependencies and you know what are doing instead of the magic happens under the hood.
Once you have linked all the frameworks to targets as per the old Podfile and added the Carthage copy-frameworks scripts then all your projects and dependencies should works as it was working with CocoaPods. Once you confirm that everything is working as expected and nothing is broken as part of these steps. This is the time to celebrate your new tool written in Swift. No Ruby and No magic under the hood.
Things to Remember
Now that, we have seen the steps to migrate your iOS app to use Carthage. There are certain things to remember about Carthage
- The idea of Carthage based on frameworks. Carthage only supports dynamic Swift frameworks, not static libraries. In future, you will only able to add dynamic Swift frameworks as dependencies. You can still add static dependency source code using --no-build option but it’s not the way how you should Carthage.
- Carthage is designed for Swift. If you still dealing with some Objective-C then fix that first before moving to Carthage.
- Migrating from CocoaPods to Carthage doesn’t solve the problems within iOS apps. It just allows you to take control of your Xcode project and makes you free from dealing with Ruby problems.
There are various benefits of using Carthage over CocoaPods. You can refer the previous post on Carthage Vs CocoaPods for the detailed comparison.
Removing CocoaPods is not a big task that you might think, using these simple five steps we can get rid of the CocoaPods from the iOS project completely and use Swift based dependency management solution for iOS apps. This could be the first step of removing Ruby from iOS app. Carthage will give you less hassle and full control on your Xcode project. Have you recently migrated to Carthage from CocoaPods? What are your experiences?