iOS: A Beautiful Way of Styling IBOutlets in Swift

This morning I saw a beautiful tweet from @jesse_squires:

Settings colors, fonts, and accessibility for UI elements in apps is always in pain. Ideally this would happen in the storyboard, but color management in the storyboard is pretty horrible (one way to mitigate this is through an Xcode Color Palette), and more advanced accessibility stuff can’t even be done in the storyboard.

So I personally prefer to do this in code – much easier to see where all the colors / font / accessibility / etc changes need to be made when the app is re-designed. I often see this translated into a super long viewDidLoad as Jesse mentions, which I try to extract into one or more functions in private extension in Swift like this:

But I really love the readability and simplicity of Jesse’s solution:

Time to refactor!

Enjoy the article? Join over 20,000+ Swift developers and enthusiasts who get my weekly updates.

  • beerrepository

    What is the benefit of putting the private UI function into an extension? Very new to Swift and have not seen that yet.

    • Kevin Xu

      Ditto, is there any benefit to doing a private extension over a regular extension for view controllers?

      • Yariv

        this is how you keep this function private. otherwise it could be called from the outside

        • Kevin Xu

          Right! Makes sense, usually I just make the functions themselves private rather than the whole extension

          • Jeremy Pereira

            It’s just an organisational thing. The extension isn’t there to group private stuff, it’s there to group UI styling stuff (hence the comment above it). He’s also decided that anything to do with UI styling is private. I don’t think either way is right or wrong.

    • Sofia

      Everything in Swift is public, so is a good technic to make private all local Ivars or methods. It’s like when you put in .m ( obj-c ) your Ivars, properties, etc; makes them privates for that particularly class

  • Lukaz

    Great tip. Readability improved a lot.

  • Jason R Tibbetts

    This is a great idea, as long as multiple outlets don’t rely on some common variable.

  • Thanks for the tip, this is an excellent idea. I’ll be refactoring some of my code as well 🙂

  • David Hoerl

    You have to be really careful with this. With viewDidLoad(), every outlet is set. Using the didSet, you can only know for sure this one outlet is set – and thus you’d better not try and change some other outlet. Worse yet, if you err, it might work when you test, and after submitting to the App Store, it might fail in the field (different setting order) – or in a new iOS update.

    • Yariv

      when didSet is called on the outlet, then the outlet is set (explains the name of the event, right :~).

      • Stefan

        Sure, but he’s saying you should not try to manipulate other outlets because you can’t be certain thy they have been set yet.

        • Yariv

          Now he changed his comment so mine seems out of context

  • Yariv

    This is a nice solution, which is also presented in the latest Stanford Coding Together videos, however I believe it could go either way –

    – Having a single method to update the UI keeps the code clean. It’s easier to calculate and set the same property to all the outlets in one location and definitely easier to make big changes when the code is grouped in one place.

    – On the other hand, if each outlet has different unrelated settings and then it is easier to maintain.

    Anyway, I enjoy reading your blog! thanks for the good tip.

  • Kakubei

    Love it, thanks!

  • vanylapep

    But then, where do you guys do the “laying out” of the outlets? Set frames and stuffs.

  • dee


  • Lasha Efremidze

    Great tip!!!!! 🙂

  • it looks good, but I prefer change property in attributes inspector, which I can see changes instantly, maybe when I face a large project, I will consider it. But thanks anyway.

  • Martin Lobger

    I just tried this technique in Xcode 7 beta using Swift 2 and realized on major drawback:
    I have a custom view (written in Objective.C) that I have inserted in Interface Builder. In that custom view I do some initialization in awakeFromNib. Unfortunately (and logically when you think of it) the didSet in the view controller is called before awakeFromNib in the custom view, leading to some of the things I setup in didSet was overwritten by the initialization done in awakeFromNib

  • Tommy

    This isn’t particularly Swift-centric; I’ve often overridden the setters in Objective-C (i.e. the approximately equivalent thing to a didSet) e.g. so that I can sort an incoming IBOutletCollection into a deterministic order.

  • Lasha Efremidze

    For styling let statements check out the Then library

  • Nico Landa

    Am i the only one that this no longer works on iOS 10?

  • Hi Natasha, good idea. I thought this a little bit further and after I went through a few iterations, I ended up with what I think is the least amount of code possible. I now have outlet collections to which I apply styling via closures to views which need similar styles.

    For example I have a bunch of views to which I apply the same tint color, so why write the same xxx.tintColor = xxx over and over again? Simply create a outlet collection e. g. “viewsWithTint” and use a forEach{ $0.tintColor = xxx } on that collection. I wrote a post about why I did this and how I did it exactly here:

  • Whilst I agree that having config code near the outlet is a good idea from a contextual sense, I actually don’t like this idea. My main reason being one of code management. Using didSet doesn’t make much of a difference when there are only one or two outlets, but beyond that you are adding a significant amount of code to the class. ie. every outlet is going to mean 4 extra lines in the class. Doesn’t sound like a lot, but it is when you have more than a few outlets.