This posts start like a lot of posts lately: I was working on an app the other day – but hey why not? I mean who writes code just to write code without actually accomplishing something with it? 😜

This time I had this overview screen with a bunch of buttons and images. A few of the images needed to be tinted with my apps primary color which I defined in a UIColor extension:

extension UIColor {
    static let primary = UIColor(red: 0.3,  green: 0.7, blue: 0.4, alpha: 1.0)
}

Back in the days, when I started learning Objective-C and even later when I started learning Swift, I used to style my views in my viewcontrollers `viewDidLoad`.

While it works, this is surely not the best way to do it. Still, a lot of my viewcontrollers nowadays look something like this:

class MyViewController: UIViewController {

    @IBOutlet weak var someImageView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        someImageView.tintColor = .primary
    }
    
}

I’m a huge fan of Storyboards to design my UIs. I just like to actually see what I’m doing, especially when setting up constraints. Yet they have their limits. Especially when it comes to applying the same styling to a lot of views, it can become cumbersome and oh boy, dare you, if you want to make a change. You will have to touch all your views again.

And here we are now, in viewDidLoad, bloating it with code to style our IBOutlets. Then I stumbled across a post from Natasha the Robot where she talks about using didSet on the IBOutlets to apply some styling:

@IBOutlet weak var someImageView: UIImageView! {
    didSet {
        someImageView.tintColor = .primary
    }
}

This opened my eyes and I immediately had to try it out. Though I use it in a slightly different way than suggested there. Because in my case, I applied the same styling to various outlets, I wanted something more generic, which is not based on the name of the property. Also I did not want to repeat the same code over and over again – thats just not good practice.

So instead of using didSet, we can simply use willSet, where we always can access the property via `newValue`. In conjunction we can define a closure to do the styling for us:

let tint: (UIImageView) -> () = { $0.tintColor = .primary }
@IBOutlet weak var someImageView: UIImageView! { 
    willSet { 
        tint(newValue) 
    } 
}

Here we can make use of some of the languages nice features. I mean, why would we want to give the child a name if `newValue` or `$0` is all you need? I like it and once you get a little bit familiar with the language, this reads a lot less strangely.

Its with Javas or C#s Lambdas. In the beginning you think: WTF is this doing? But once you learn where what is coming from and how the compiler can infer all these types, it becomes pretty straight forward.

So far so good, we have a tinting close which we can apply to our outlets in willSet but thats still a lot of useless, duplicated code, right?

@IBOutlet weak var someImageView: UIImageView! { willSet { tint(newValue) } }
@IBOutlet weak var someOtherImage: UIImageView! { willSet { tint(newValue) } }
@IBOutlet weak var yetAnotherOne: UIImageView! { willSet { tint(newValue) } }
@IBOutlet weak var andSoOnAndSoOn: UIImageView! { willSet { tint(newValue) } }

I think we can do better. But how, you might ask? Well if you haven’t guessed it already (I mean it’s in the title of this post πŸ€“), the solution are outlet collections. These are the great things which, as the name suggest, group a bunch of IBOutlets into one array but without actually writing code.

Simply create a IBOutlet array and connect it to each outlet you want to have in your collection. Then, in willSet, just iterate over the collection and apply the styling to each element:

@IBOutlet var imageViewsToTint: [UIImageView]! { 
    willSet { 
        newValue.forEach { $0.tintColor = .primary } 
    } 
}

Well, now we are talking. Did you see what we just did? We created a way to easily apply styling to our Storyboard views by simply dragging that cool blue line onto a view. Isn’t that cool? And the best thing? You can create multiple outlet collections to apply different styles.

Why limit yourself to UIImageViews? Make the collection of type [UIView] and you can mix it how you like it. Have a collection for tinting, one for content modes, one for background colors. What I probably love the most about this is not only that you can immediately see which views get which style (which I find harder when doing everything in code), but the fact, that I now can tint all the images with one single line of code. Having so less code duplication lets my heart beat faster and I now love Swift even more.