Modularize an iOS application
“Just leave your computer and go grab a coffee, the app is compiling !”
Who else can relate ? That’s the most frustrating feeling when you only need to change a single line in your code and then the whole app compilation starts over… and can take up to loooong minutes !
As your iOS app is getting bigger and bigger, the compile time is growing too ! This is the first reason why I started to look at frameworks.
By default, you only have one target for your app, and possibly other targets for unit testing, and UI testing. But if your app is developed on one single target, when you change one line of your code, Xcode will eventually rebuild the whole app, depending on which file you changed, and what data you changed (variable name, access control, string content…).
But if you came to read this article, you may know how annoying it is to wait 5, 10 or even 15 minutes for the app to compile (if you are working on a big project). This problem is even more important when you are many developers working on the app : the waiting time is multiplied by the number of developer. In that way, you are wasting a lot of time and your efficiency is considerably reduced.
This is a very common problem on big apps and I think the way it should be solved is by dividing the app into different frameworks.
“What exactly are these frameworks ?!”
You’re right I haven’t defined it yet. So frameworks are parts of the projects that can be built separately and they have their own target. In this article I may call them “modules”.
You can manage to not only build, but also run a module by creating a sample app that import only the framework concerned, and using the features contained in the module.
Therefore, when you are changing the code of a framework, only this framework will be rebuilt at the next compilation, because other frameworks and targets haven’t changed. This is where a precious time is saved.
In fact, creating frameworks has many other benefits.
For example, it clearly improves your code architecture. By creating modules you separate you app into different parts and all of these parts can have their own unit test target, and UI test target ! That means you have a better code structure, and can test your code by framework. We all know that the more separated the code is, the better.
Apple recommends to create frameworks so if your app respects these best practices, maybe it can make your upload on the AppStore easier ?
There is also another benefit : a framework can be imported into another project.
Now you want to create frameworks ! In addition to all of these benefits, Apple made it very easy for us to create frameworks within Xcode. Just go onto “File -> New -> Target” and choose Cocoa Touch Framework, as shown below. Your new framework will be displayed in the target list. Here I have also created the unit test target for my framework.
You may want you framework to depend on another one. For example your CustomerAccount framework may need the Network framework for all network management. To make a framework depend on another one, you will need to check the target scheme. In the build tab, add the module. You will need to add this module in the build phases of the parent target too.
“What frameworks should I define ?”
That’s an interesting question, and I think it can have multiple answers. On the project I am working on, we chose to divide modules into two different categories :
- Feature modules : Modules that represent a feature of your app. For example, you could create a module Account for your customer account part.
- Kit modules : Modules that represent a technical part of your app. You could have for instance a Network modules which handles the networking layer, a UIComponent module representing the UI elements of your app, a Localization module for your wordings… You can eventually create a Core module for everything that is connected to many parts of your application and is too hard to isolate.
If you have a local database, maybe a Storage module could be convenient to handle the database requests.
A feature module should obviously import one or more kit modules. A Kit module should NOT import a feature module. And a feature module should not import another feature module.
“Creating frameworks is so helpful and easy, what’s hiding behind it ?”
Yes, it is very helpful and it can be easy to divide your app into frameworks, but some cases can get you into trouble. Here is a short list of problems that I have encountered during the modularization of the app I am currently working on :
- Handle links between different modules
- Avoid cyclic dependencies between modules
- Choose where to develop a feature that is shared across several modules
- Handle images between all different bundles
- And the most difficult one : handle exportation into frameworks of an existing massive app which already has many dependencies
I come across all these problems in detail in this medium post, because some cases need a concrete example.
“ What can we say in a few words to conclude ? “
In conclusion, my feedback on this modularization process that I came across on my project is pretty clear. Frameworks are useful, they allow to have a decent architecture, and I really prefer to develop on this project since it has started to become modularized.
However, even though it has many advantages, this process can lead to some complicated situations and you have to be careful when dealing with modules.
Certainly, the sooner you start to modularize your application, the better. It is more difficult to try to modularize an existing app, and it gets even harder if it’s a big app. So think about it when building a new iOS app !
You can check the github project, showing an iOS app modularization, how to use pods inside your modules.
If you want to learn more about the common problems you could encounter when modularizing your app, check my post dedicated to it !