Choose Your iOS Dependencies Wisely
Dependencies are vital for most iOS projects. They allow us to speed up development and not reinvent the wheel every time we need components such as networking, rendering, chat, calendar, and many others which can be common to different types of projects. It's also an efficient way of deferring code maintenance to a company or open source community, since they'll fix bugs, add new features, and update the code for you. Using dependencies, we're able to focus our working hours on what sets our iOS app apart from the rest.
However, any seasoned iOS developer knows dependencies can often hold your iOS project back and negate the time saved if you don't choose them wisely.
Fortunately, there are rules which you can follow when choosing iOS dependencies to avoid most, if not all, of the downsides. In this post, I present five rules for iOS dependencies that can save you many hassles in the future.
Open-Source or Source-Available
You should always prefer using dependencies that are Open-Source or Source-Available. These will allow you greater freedom to accommodate changes in requirements, fix bugs yourself, step through code, and debug things easily. It will also help you find out undocumented behaviors, know what it does for sure, and not risk undesired malicious code or analytics to run in your apps.
Closed-Source dependencies distributed in a compiled format such as
.xcframework, are an opaque box. It's hard to know for sure what it's doing. What data is it collecting? What is it sending to the server? Can it crash my app under certain circumstances outside my control? How long will the maintainer take to fix a bug?
Closed-Source SDKs are constantly harming productivity and reducing the choices that iOS developers can make. For example, Facebook's iOS SDKs frequently crash other apps for no good reason, without any possibility for developers to act on it other than removing the SDK altogether. Another SDK was found to steal user data and attempt to cover its tracks. They're best avoided if there are competent alternatives.
Before you decide on a dependency, check how long ago its last updates were made. If it's days or weeks, it's more likely that it's compatible with the latest iOS versions, and you'll be able to count on updates for a while. It's also more likely that the maintainers are still around to help if you have a question.
On the other hand, if it's been months or years since the last updates, you should consider not using this dependency. It's unlikely that it's still compatible with the latest iOS or Swift versions, and even less likely that the maintainer is around to help you or provide any new updates.
Inactive projects are generally bug-ridden and should be avoided, but it's still possible to use them if you're willing to fork them, fix the bugs you encounter, and become a maintainer. However, most of the time, it can be more productive to build the component you need from scratch.
Built with Swift
Swift has been around for five years. It's now considered a mature language and has greatly increased productivity and code correctness over its ancestor, Objective-C. It's no mystery that these improvements are carried over to the dependencies you use. Dependencies built with Swift are likely to be more stable and fit in seamlessly with the Swifty patterns and features developers know and love, such as protocol oriented programming, optionals, generics, collection types, first class functions, and others.
Alternatively, if you choose to use a dependency written in Objective-C, you'll likely run into old patterns and naming conventions that are not as nice to work with. Objective-C dependencies are also more likely to contains bugs related to null references.
It's not a complete deal breaker if a dependency is written in Objective-C, as long as it's still actively maintained. Yet, I've found that every Objective-C dependency I wanted to use had an excellent and newer alternative written in Swift. For example, over the years, I've replaced SDWebImage with Nuke in almost all my projects with great benefit.
Dependencies that are maintained by a company tend to be more reliable when compared to dependencies that are supported by a community. It's less likely that a company-maintained SDK or library will be abandoned if it's vital to that company's business.
For example, it's highly unlikely that a library like Realm or IGListKit will be abandoned, as they're maintained by a business as well as an active community. In some cases, companies may also offer dedicated support in case you need the extra commitment.
A welcoming community also goes a long way in ensuring a smooth experience with an SDK or library. Most of the time, except for company support or paid support plans, you'll rely on this community to help you when you're having problems or when you want to contribute back to the project. If it's a community that is patient with newcomers and is receptive to new ideas, then you're more likely to have a good time depending on them.
These are the characteristics I look for when searching for iOS libraries and SDKs. It's challenging to find a library which checks all these boxes, but keeping these in mind helps compare the options and choose the one that will give you fewer problems in the future.
- Swift WebSockets: Starscream or URLSession in 2021?
- Publishing Android libraries to MavenCentral in 2021
- Activity Feed Personalization 101: Top Feed Features to Improve User Engagement
- Singleton vs Dependency Injection in Swift
- Jetpack Compose: First Impressions and Learning Resources
- macOS Performance Comparison: Flutter Desktop vs. Electron