Voilà! Once you’ve got your pipeline set up, you can keep track of any changes to your colour semantic definitions with git and still take advantage of the power that colour assets deliver.

We went as far as extracting this into its own separate framework that we could share across different projects, as a “drop-in” design-approved colour scheme for any app.

However, this is also where we began to discover some of the rough edges of this feature. If you are interested in developing a similar setup for your app, it’s important you know that consistent and designer-friendly colour management comes at a cost. Below are some of the issues we’ve found with iOS 11’s Colour Assets and the ways you can deal with them.

Named Colours Across Bundles

Remember how we mentioned we were excited to extract our semantic colour references into a reusable framework? What felt like an inarguably good architectural decision turned out to have major side effects. The moment we linked our framework to an app and tried to refer to any of the named colours, they stopped working entirely.

What happened?

If you are familiar with the way, for instance, UIImage(named:) works, you’ll know what’s going on. In iOS apps, the main bundle takes precedence by default and could be the only place where your app looks for resources, unless told otherwise.

On the code side of things, there’s an easy fix. Whenever you call UIColor(named:) , simply ensure to set the optional in bundle: parameter.

// A global property for easy reference

let colorFrameworkBundle = Bundle(identifier: "com.myfirm.MyUIColors")! // In your ViewController:

label.colorText = UIColor(named: "PrimaryText", in: colorFrameworkBundle, compatibleWith: nil)

The problem is much less straightforward for colour references in Storyboards and XIBs. And, once again, if you’ve dealt with having to embed images across bundles, you’ll know what the issue is:

Interface Builder does not support referencing images that live outside the bundle of the Storyboard or the XIB, and that has been a problem for a long time. (And to some people, this has been one of the many reasons to not rely on Interface Builder altogether, though that’s a whole other topic in itself.)

Unfortunately, the way colour assets are represented in the generated XML is very similar: they do not contain any references to the bundle where the asset lives.

When you use a colour asset across bundles this way, it won’t fail completely though, unlike the images. You may notice how Xcode helpfully provides a fallbackColor , which contains the value the IDE retrieved from the catalog at the time when you picked the colour. At runtime, iOS will apply this fallbackColor , and you’ll see a warning in the console that’s something along these lines:

2018-04-26 17:30:30.009855+1200 MyApp[82987:11407859] WARNING: Unable to resolve the color named "PrimaryText" from any of the following bundles: com.myfirm.MyApp, com.myfirm.MyApp

This will become a problem the moment the asset is modified, since this static fallbackColor in XML will get out of sync with the true colour value, defeating the purpose of the whole feature in the first place.

It’s disappointing to see that Apple did not learn from the flaws of image support in IB and took the same shortcuts with implementing colour assets. Let’s hope that the most exciting minor feature of iOS 12 will be better multi-bundle interplay. rdar://35764499. (Update: it wasn’t. While Xcode 10 introduced some minor improvements to the way named colours are shown in IB, iOS 12 does not address any of the issues described in this article.)

The workaround for this in the meantime would be automatically copying the asset catalog with the colours into all bundles that need them, at build time. If you use Cocoapods to assemble your project, the podspec for your private colour library may contain something like this:

spec.resources = [

"MyColorLibrary/**/*.{xcassets}"

]

This will ensure that the asset catalog is added to the main bundle of your final product, thus becoming visible to all XIBs and Storyboards that reference it.

If you don’t use Cocoapods or if your project’s internal dependencies structure is sufficiently complex, you may need to invest in custom tooling to automate this process for you. No matter how you set this up though, ensure that you respect the “single source of truth” concept, whereby the copies of the original asset catalog can never be accidentally modified and committed independently.

Deferred Runtime Colour Application

Even if your app is a single-bundle project with a straightforward structure, and you aren’t interested in setting up fancy pipelines for generating asset catalogs on the fly, there are still other gotchas with using colour assets in their current form.

One crucial aspect, which could make you lose hours tearing your hair out if you aren’t aware of it, is the deferred runtime nature of colour assets when used in Interface Builder.

You can easily observe this by configuring a XIB or Storyboard that contains a named colour. You then modify or override that colour at runtime, with code: