Swift Tip: Custom Views Without Subclassing
UIKit is a framework that relies heavily on subclassing. While subclassing can be very useful, sometimes we can get away with much simpler techniques for composing views. As an example, we'll build a simple alert popup from scratch:
One reason for subclassing is to extend a class with shared functionality. For example, you might create a subclass of UILabel
, and set some common properties. Where we just want to set properties we don't have to create a subclass, but can create a convience initializer instead, using fileprivate
to keep this initializer local to the current file:
extension UILabel {
fileprivate convenience init(text: String, style: UIFont.TextStyle) {
self.init()
font = UIFont.preferredFont(forTextStyle: style)
self.text = text
textColor = UIColor(white: 0.1, alpha: 1)
backgroundColor = .clear
}
}
If we want to create a reusable way to compose multiple static views, we could create a custom UIView
subclass, but it's also perfectly possible to create a function. For instance, the following function builds our custom popup with an icon, a headline and some detail text:
func buildPopup(icon: String = "ⓘ", headline headlineText: String, body bodyText: String) -> UIView {
let container = UIView()
container.layer.cornerRadius = 10
container.layer.masksToBounds = true
let header = UILabel(text: icon, style: UIFont.TextStyle.largeTitle)
let headline = UILabel(text: headlineText, style: .body)
let body = UILabel(text: bodyText, style: .caption1)
let effect = UIVisualEffectView(effect: UIBlurEffect(style: .light))
container.addSubview(effect, constraints: .allEqual())
let stack = UIStackView(arrangedSubviews: [header, headline, body])
stack.axis = .vertical
stack.alignment = .center
container.addSubview(stack, constraints: .allEqual(margin: 30))
return container
}
This technique is really simple — after all, it's just a function — but it does have some drawbacks. For example, changing properties after construction isn't so simple. However, if all you're doing is building the view hierarchy once, and you never intend to change it again, a simple function might be all you need.
In Swift Talk Episode 7 (a public episode), we used a different technique to compose static views, and in Episode 54 we extended that technique to include callbacks.
In our book App Architecture, building the view hierarchy is an essential part all five design patterns, and we look at many different ways to achieve it.
If you’d like to become a Swift Talk subscriber, you'd be very welcome! — we have monthly or yearly plans, for individuals or teams, with new episodes every week. 🤓