Creating a custom UIView from a Xib in Swift
Why is it important? ๐ค
Creating custom views is an underrated habit that can benefit any codebase for a variety of reasons.
Reusability
Very often, the same group of design elements will be on multiple screens across an app. It makes sense to group them in a custom UIView
to reuse the same design and logic at multiple places.
- Enables reusable design and code
- Saves time
- Facilitates changes
Readability
When a screen has many design elements, the UIViewController
associated with it can get messy.
- A lot of outlets
- A lot of configuration logic
Grouping those elements in a custom UIView
move the outlets and the configuration logic to the custom view, making the view controller smaller, easier to read and maintain.
Testability
Testing every state of a view controller that has a lot of outlets and design logic can be time-consuming and hard to maintain. However, if the view controller is built from a few custom views, those can be tested independently. This improves your tests and make them:
- Easier to maintain
- Smaller and faster to write
How can I create a custom UIView from a Xib? ๐
It is relatively easy to create a custom UIView
from a Xib
in Swift. There are multiple steps to it though. It all starts with a simple protocol.
Protocol
First, we need a protocol to give a subclass of UIView
the ability to attach the content of Xib
to its content view.
protocol CustomViewProtocol {
/// The content of the UIView
var contentView: UIView { get }
/// Attach a custom `Nib` to the view's content
/// - Parameter customViewName: the name of the `Nib` to attachs
func commonInit(for customViewName: String)
}
extension CustomViewProtocol where Self: UIView {
func commonInit(for customViewName: String) {
Bundle.main.loadNibNamed(customViewName, owner: self, options: nil)
addSubview(contentView)
contentView.backgroundColor = .clear
contentView.frame = bounds
contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
contentView.translatesAutoresizingMaskIntoConstraints = false
}
}
Xib file and UIView subclass
Letโs say our custom view is called MyCustomView
. The creation process would be the following:
- Create a
UIView
subclass calledMyCustomView
- Create a
Xib
file calledMyCustomView.xib
Then, we need MyCustomView
to conform to CustomViewProtocol
.
After this step, it is crucial to make sure the commonInit(for customViewName: String)
method is called when the custom UIView
is initialized.
final class MyCustomView: UIView, CustomViewProtocol {
@IBOutlet var contentView: UIView!
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit("MyCustomView")
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit("MyCustomView")
}
}
Thatโs it, you have attached the content of a Xib
to your custom UIView
.
Usage
To use your custom view, add a UIView
to your UIViewController
in storyboard and set its class to be your custom view. Thatโs it! ๐
Note
If you need to handle certain events happening in your custom view from your view controller I would recommend using the delegate pattern.