Skip to content

Instantly share code, notes, and snippets.

@vincent-pradeilles
Created August 9, 2017 19:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vincent-pradeilles/cb06a73011030ce975500f01e7e9363b to your computer and use it in GitHub Desktop.
Save vincent-pradeilles/cb06a73011030ce975500f01e7e9363b to your computer and use it in GitHub Desktop.

Designing an iOS framework with overridable resources

A demo project that illustrates the content of this article is available on my GitHub.

Why does it matter?

Frameworks are, by definition, meant to be used in many diverse contexts, that's why developers pay special attention when they design them, in order to let their integration be as seamless as possible.

When it comes to API design, we all have a pretty good sense on how to achieve this goal. But an iOS framework is not only made of code: it also contains resources. And in many cases, being able to override such resources might be a mandatory prerequisite for an app that integrates the framework.

For the purpose of this article, we will assume that we are working on a series of white-label apps. Those apps deal in the same business logic, but each one does so using its own branding. In such a situation, a framework that provides the common business logic and allows the app to override its default resources is a great tool to streamline the development workflow.

How to achieve it

An iOS framework is basically a container that stores some code, along with a bundle in which resources are stored.

Our first step toward our goal will be to make this bundle easily accessible from inside the framework:

https://gist.github.com/08ebe872c5ea0dac0452af10f1db0efd

Then, we create a global function that will allow us to instantiate an overridable image. The strategy behind this function will be to attempt to load an hypothetic overridden image provided by bundle of the app, and if none is found it will then default to the one stored in the framework:

https://gist.github.com/aa04546d2012e7fa79c1c325918afebb

This strategy can also be applied to storyboards (and to basically any binary resource stored in the bundle):

https://gist.github.com/23e99018074dd281c81a10319ec4ef0a

Lastly, to handle the case of localized strings, we will attempt to localize the key using a table stored in the bundle of the app and — by convention — named Override.strings. If the key was not found in this table, we then fall back to the one contained in the framework:

https://gist.github.com/14b6a2b56b8058ba89515664b1e73731

Discussion

The aim of this article is to describe a general strategy that can be applied to tackle the issue of designing a framework whose resources are overridable. The API used to achieve it was voluntarily presented in a very raw fashion, using global functions.

In practice, a developer might want to add some additional syntactic sugar. For instance, using an extension as follows:

https://gist.github.com/3961e7a216555a18ba687b80c7c39398

It might be tempting to fully integrate the overriding API into UIKit through the use of swizzling. I, personally, would strongly advise against it, because modifying the expected behavior of SDK-level API will revel misleading and hard to maintain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment