Using storyboards is a mess when there's more than one developer working on a project (merge conflicts are sure to happen and are horrible). Even for a one developer project, building views programmatically is advised.

Define subviews

class SomeViewController: UIViewController {
	private lazy var someLabel = UILabel().apply {
		$0.text = "This is a label"
		$0.textAlignment = .center
		$0.textColor = .black
	}
}

class SomeView: UIView {
	private let someLabel = UILabel().apply {
		$0.text = "This is a label"
		// ...
	}
}

We use the apply custom extension to configure the view after creating it. This reduces boilerplate code when creating views and reduces visual clutter too.

If we create a view using a factory function or any method that isn't a constructor, we should add a type annotation so the view's type is clear:

private lazy var maskLayer: CALayer = makeMaskLayer().apply {
	$0.cornerRadius = 10
	// ...
}

<aside> 🛠 Note: apply is a custom extension. Check HelperKit — Standard Extensions.

</aside>

Constraints

Since we build views programmatically (i.e. without storyboards) we have to write auto layout constraints by code. To ease up development, we use the SnapKit library.