One of the first principles of engineering is to not reinvent the wheel. When working on a project, everybody builds on top of code written by someone else.
At the very basic level, we all use the frameworks provided by Apple:
StoreKit, and so on.
On top of that, every app has a layer of common problems with the other apps. Well-known problems are solved by libraries that are used by thousands of developers. This has contributed to making those libraries a robust, tested, and reliable piece of software. Thanks to these libraries, we can focus on the business logic of our app and stop worrying about lower-level tasks like networking and persistence.
Today, I’d like to talk about the most important open-source libraries that we use at Bending Spoons — libraries that you can also use. I will categorize them by the problems they solve. So, let’s start!
One of the first decisions we need to make is what is the best architecture for our app. Apple pushes for the MVC. While this is a good choice for small projects, it does not scale well. For bigger projects, we are getting used to MVVM and, if possible, unidirectional data flow.
This architecture scales pretty well and enables some advanced features like modularization and testability. However, it requires some boilerplate. Libraries help to reduce this boilerplate.
Katana and Tempura
These are two libraries we developed internally at Bending Spoons. Katana implements the unidirectional data flow concept and provides the infrastructure to let the information flow from the state to the UI. Tempura is the actual implementation of the MVVM design pattern and is very reliant on Katana.
You can read more about how to set up a project with Katana and Tempura in this series of articles.
The Composable Architecture (TCA)
Another unidirectional data flow library focused more on composability and testability. It follows the Redux approach more strictly than Katana and Tempura. However, in its basic form, it relies a lot on Combine and it comes with out-of-the-box support for SwiftUI (although you can use it with UIKit, writing a small wrapper).
You can read more about how to use this architecture in this series of articles.
It does a lot to simplify configuring network requests and pinning a certificate, and it abstracts several other tasks. Starting from version five, it does not support background download, but this use case appears less often than you may expect.
Note: on September 2019, Apple released Combine. In September 2020, Combine was improved a lot. With this new framework, the need for a networking library will fade somewhat. If you are going to create for iOS 13 and up, then chances are you won’t need Alamofire.
Strongly coupled with the networking problem — but not just with that — is asynchronous code. Closures are great callbacks — definitely better than Objective-C’s blocks — but they can still create the (in)famous callback hell.
Promises are a better alternative to use callbacks when dealing with asynchronous code. A promise is a wrapper around an async call that promises to eventually contain a value of a predefined type. They usually come with the
await keywords (or methods in Swift) — these let the code wait for the promise’s execution and let the processing proceed when the promise holds the value. The best thing about promises is that they allow us to write asynchronous code as synchronous.
You can read about more advanced promises’ design patterns in this article.
Note: In September 2021, Apple may release a version of Swift with
await backed directly into the language. You can read the technical proposal here. If that’s the case, the promises library could fall from grace within a few years.
If you’ve tried out our beloved Katana and Tempura, you have seen that they download a library called Hydra. This library implements the Promise pattern. It is well maintained, well documented, and easy to use. Give it a try!
I tried the library only once and found it slightly harder to use than Hydra, but the two are pretty much equivalent in terms of features.
Sooner or later, you’ll need to load an image from a remote URL. Surprisingly, this is a long-missed feature of UIKit, while other languages offer components that support this behavior natively (both Flutter and React Native have components that can load images from a remote URL).
This is an additional framework that we can decide to import if we’re already using Alamofire. AlamofireImage relies on Alamofire to download and cache the image.
I have never used this library directly, but it’s worth mentioning, given its strict bond with Alamofire.
This is the image loading library, with an astonishing 18.1k stars on Github. It has all the features you need to load an image. Completion, cancellation, custom converters, placeholders, and so on.
It’s extremely easy to use and super easy to adopt in your app — it’s based on the UIKit’s
Creating a layout is one of the most boring tasks in coding a UI, in my personal opinion. This task is even more boring thanks to the low level of abstraction we have to work with when writing a layout in code. And don’tget me started on constraints — they’re so much more complex than the basic
frame-based layout, that Apple has created a small language just to describe them more easily!
Lucky for us, we can leverage PinLayout. This library allows us to define layouts in a declarative way, describing where to put a view in relation to the parent or to its siblings. The library is pretty powerful and allows the implementation of complex layouts with ease.
AttributedStrings are another verbose and cumbersome Apple’s API. They rely on a dictionary of attributes to configure how the string has to be rendered, which makes it quite hard to remember the keys and how to use them.
Also, if you need to implement a label with different styles, vanilla
AttributedStrings APIs force you to work with ranges and subranges. These APIs are extremely error-prone.
You can find a list of all the
AttributedString’s attributes in this article.
To reduce verbosity and increase safety, BonMot is my library of choice. With this library, we can create values that contain a style definition, and we can then reuse those styles across our app. It supports an XML-based language to define different styles within the same strings, abstracting away all the complexity!
UIKit offers a good pair of APIs to implement animations. We can choose between
UIView.animate, for simple tweening from a value to another, and
animateKeyframes for a more fine-tuned approach. However, both these APIs require some work on the development side. Furthermore, complex animation may be quite difficult to implement with a code-first approach.
Lucky for us, Airbnb comes to the rescue. They have developed Lottie, a library that integrates After Effects’ animations into our apps. The steps are:
- add an
AnimationViewcomponent to our
- load a
start(by calling the
NOTE: If you don’t have a motion designer, you can choose from a huge library of animations from this website.
In-app purchases (iAP) are a monetization standard these days. In fact, the entire monetization strategy of many companies is based on them. Despite that, in-app purchases are a complex matter to implement.
iAP APIs are no joke. You have a manager component (and a delegate) to retrieve the list of products from the apple server (and you only get their IDs!). Then you need to match those IDs with a set of meta-information manually created on AppStore Connect — and that cannot be queried easily.
You also have a payment queue (with another delegate) to perform purchases/restores and to listen for changes in the transaction’s state.
Finally, you should validate the recipe for the purchase. Everything gets more complex if we consider different storefronts, special content to be delivered, or sections of the apps that have to be unlocked.
Let’s forget about all the iAP’s complexity by using SwiftyStoreKit. This is a Swift library that takes care of all the managers and delegates for you. We used it a couple of years ago to implement payments in our Playond service and the library served us well.
Validating the receipt is a complex matter and should be done server-side for security reasons. Chances are that you don’t have a backend (using some serverless technologies like Firebase) or maybe you don’t know how to implement a backend. There are a few services that provide the Receipt Validation functionalities so that you don’t have to worry about implementing them.
I have never used these services, so I can’t guarantee that they work well. However, they look interesting and they can save you a lot of headaches with iAP. Trust me: every time we’ve had to work with that part of the Apple ecosystem it has always been a blood bath.
RevenueCat is a service that offers receipt validation and some other related services. It offers several integrations and the free tier allows to handle 10k transactions per month, for free. With the lowest tier (0.99 $) you can make up to 10k$/month without costs.
Adjust is a service that is mainly used to attribute installs coming from advertisements. However, it offers a receipt verification service as well, for both iOS and Android.
In this article, I presented a set of libraries we use or have used in the past at Bending Spoons. They simplify well-known problems and let us focus on the business-critical part of the apps. They’re a solid starting point for building powerful apps.
I think that anyone, even indie developers, could benefit from these libraries and I’m pretty sure there are a ton of other very useful libraries that you can use to solve common problems (caching, for example.)
Remember: If you have a problem, there’s a very high probability that a library has been already developed for that. So, start with a search!