---
title: 'Building iOS Interfaces: Subclassing Views'
teaser: The custom button we previously implemented looks all good and dandy, but
  we can't possibly be expected to repeat that process for each additional button.
  Enter subclassing.
tags: ios,design,mobile,swift
author: Reda Lemeden
published_on: 2016-04-28
---

*This article is Part 4 of the __Building iOS Interfaces__ series which tackles
*the how and why of implementing iOS designs without prior native programming
*experience--perfect for Web designers and developers. You can find the previous
*articles here: [Part 1] -- [Part 2] -- [Part 3].*

In the [previous article][Part 3], we implemented a custom button by going back
and forth between Interface Builder and Swift -- a process that would quickly
become strenuous if repeated over and over, unless you are building a flashlight
app with a single button in the UI. Putting aside the fact that repetition is no
fun, updating even the smallest details in the future would require going
through every single button instance, and that's untenable. There *is* a better
way, and we're here to talk about it.

![Final Result](https://images.thoughtbot.com/building-ios-interfaces-custom-button/ButtonOutcome.png)

### The Proper Way

As we have [previously mentioned in passing][subclassing], subclassing is the
process of creating a new class that inherits the properties and methods of an
existing one. The subclass can optionally override the superclass's behavior,
and that's exactly what we need to do to customize the default look of the
`UIButton` class. Let's take a look at how this works in practice.

Open the Swiftbot project if you happen to have it locally, or download it as we
have previously left it off [from GitHub][download link].

Add a new file to the project by right-clicking the parent group in the project
navigator, then selecting *New File...*.

![New File](https://images.thoughtbot.com/building-ios-interfaces-subclassing-views/NewFile.jpg)

Select *Source* under the *iOS* section, then pick *Cocoa Touch Class* from the
template collection.

![Cocoa Touch Class](https://images.thoughtbot.com/building-ios-interfaces-subclassing-views/CocoaTouchClass.jpg)

Name your class *RoundedCornerButton* then set *UIButton* in the *Subclass of*
field. Leave the rest unchanged. On the topic of naming, classes in Swift are
named in *CamelCase*. It's considered good practice to pick a name that
describes the purpose of the class.

![Subclass Naming](https://images.thoughtbot.com/building-ios-interfaces-subclassing-views/NameClass.jpg)

In the new Swift file, go ahead and delete all the comments -- lines starting
with `//` -- the end result should look like this:

```swift
import UIKit

class RoundedCornerButton: UIButton { }
```

This snippet above is the bare minimum needed to create a subclass in Swift. As
introduced in [the first article][languages], the `import UIKit` part serves to
give us access to the APIs defined in that framework, namely the `UIButton`
class in this case.

Creating a subclass is not enough however, since Interface Builder still
considers our button a *UIButton*. Additionally, our subclass will remain a
carbon-copy of its superclass until we add some implementation code.

### Classes & Instances

We've [previously][conceptual overview] noted that each control is represented
by a UIKit class in Swift. What we've left out however, is that a class is
nothing more than a blueprint defining how a view object should look and behave.
In other words, they are of little use on their own.

This is where instances come into play. An instance is an object that was built
following the specifications provided by a given class. In our example, the
button we added in IB is an *instance* of the `RoundedCornerButton` class.

![Class vs Instance](https://images.thoughtbot.com/building-ios-interfaces-subclassing-views/ClassInstance.jpg)

Notice how the `UIButton` class states that every button should have a
`buttonType` property, without actually setting its value. It's up to the
instance to decide what type of button it wants to be.

Now let's make our button an instance of the new subclass.

In the storyboard, select the button and look for the ID card icon in the
Utilities sidebar to the right. This takes you to the *Identity inspector*,
where you can change attributes that are unique to this button instance, such as
the class and the identifier.

![Identity Inspector](https://images.thoughtbot.com/building-ios-interfaces-subclassing-views/IdentityInspector.jpg)

In the *Class* field, type the name of the subclass we created earlier. This
makes this specific button an instance of the `RoundedCornerButton` class,
meaning that any custom behavior we add in code will be applied to it.

![Set Class for Button](https://images.thoughtbot.com/building-ios-interfaces-subclassing-views/ChangeClassIB.jpg)

Now that we got this out of the way, let's remove the outlet connection that
[we've created in the previous article][outlets] since we will no longer need
direct access to our button instance in the view controller. We can achieve that
in several ways, the easiest of which would be heading to *Connections
inspector* and clicking the *x* button next to the `roundedCornerButton` outlet
in the *Referencing Outlets* section.

![Remove Outlet](https://images.thoughtbot.com/building-ios-interfaces-subclassing-views/RemoveOutlet.gif)

With the outlet gone, we need to remove all references to the button in our
`ViewController.swift`. Go ahead and delete all the code in the class
declaration so as it ends up looking like this:

```swift
class ViewController: UIViewController { }
```

We are now almost done with Interface Builder in this exercise. Before we go
back to our subclass however, we need to shed some light on how you typically
approach using subclasses as a way to extend the stock UIKit controls.

### The Subclassing Game Plan

When it comes to subclassing, the most common -- and often challenging -- task
is figuring out what *methods* and *properties* to override and in which order
your execute your custom code. If things go wrong, and they will, it's often
because you are overriding the wrong method or doing things in the wrong order.

For UIView subclasses, you typically want your custom styles to be applied as
soon as the view is loaded. Common methods to override include:

-   `awakeFromNib()`, which is called when the view is loaded from IB.
-   `drawRect(_:)`, which is called when the view needs to draw itself on
    screen.
-   `layoutSubviews()`, which is called when the view needs to determine the
    size and position of its subviews.

There are obviously more methods than we can cover in this tutorial and, if you
are curious, you can read up on each in detail on the [official UIView
documentation].

### Override

In order to override a method in Swift, we use the `override` keyword at the
beginning of the declaration like so:

```swift
class RoundedCornerButton: UIButton {
  override func awakeFromNib() { }
}
```

We overrode `awakeFromNib()` since it seems like a good place to start adding
our layer customizations. If your run the app after these changes, you will
notice that there are no noticeable changes save for the sharp corners. That's
expected since we removed the code that set the `cornerRadius` on our instance's
layer in the view controller.

In the previous code snippet we achieved that with this line:

```swift
roundedCornerButton.layer.cornerRadius = 4
```

Since we are doing this directly from within the button subclass, we can
drop the `roundedCornerButton` reference in the declaration above:

```swift
class RoundedCornerButton: UIButton {
  override func awakeFromNib() {
    layer.cornerRadius = 4
  }
}
```

Note that `layer` is equivalent to `self.layer` in his case, `self` being a
reference to the instance. That said, `self` is rarely required in Swift, so
it's safe to drop unless the compiler suggests it.

Go ahead and run the app. Our button should be basking again in its
rounded-corner glory.

![Rounded Corner Button](https://images.thoughtbot.com/building-ios-interfaces-subclassing-views/RoundedCornerButton.jpg)

Now here is the fun part: if you duplicate the button in IB -- by alt-dragging
it to a new location -- the new instance will look identical, without having to
manually change its properties in the view controller.

![Two Rounded Corner Buttons](https://images.thoughtbot.com/building-ios-interfaces-subclassing-views/TwoRoundedCornerButtons.jpg)

There is one little issue however. Currently we're setting the background color
through IB. That means that we decide later to change all buttons in our app to
a new color, we have to go through each button object in IB and manually change
the background color attribute.

We can fix that by changing the property directly in the subclass so that all
rounded-corner buttons are the same color:

```swift
class RoundedCornerButton: UIButton {
  override func awakeFromNib() {
    layer.cornerRadius = 4
    backgroundColor = UIColor(red: 0.75, green: 0.20, blue: 0.19, alpha: 1.0)
  }
}
```

If you run the app, both buttons should be using this *Tall Poppy* color -- name
courtesy of [Kromatic]. The same approach could be used for the font, text
color, or even brand new behavior such as an *in-progress* state.

![Two Red Buttons](https://images.thoughtbot.com/building-ios-interfaces-subclassing-views/TwoRedButtons.jpg)

### Closing words

Subclassing is a powerful tool to have at one's disposal when building iOS
interfaces. You can still do without it, but it will go a long way in helping
you build a sane, scalable, and modular design system.

[Part 1]: https://thoughtbot.com/blog/building-ios-interfaces-swift-primer
[Part 2]: https://thoughtbot.com/blog/building-ios-interfaces-views
[Part 3]: https://thoughtbot.com/blog/building-ios-interfaces-custom-button
[outlets]: https://thoughtbot.com/blog/building-ios-interfaces-custom-button#outlets
[download link]: https://github.com/thoughtbot/Swiftbot/archive/b4e140f1f23bc103a490949140dcc0b2f1deb2f8.zip
[subclassing]: https://thoughtbot.com/blog/building-ios-interfaces-views#uiview
[languages]: https://thoughtbot.com/blog/building-ios-interfaces-swift-primer#languages
[conceptual overview]: https://thoughtbot.com/blog/building-ios-interfaces-views#conceptual-overview
[official UIView documentation]: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/index.html
[Kromatic]: https://kromatic.thoughtbot.com
