Making custom designable UI components

Valerii Che
Bumble Tech
Published in
5 min readAug 1, 2018

Hi there! I’m Valera, iOS Padawan at Badoo. Here in our company we are crazy about UI and spend plenty of time designing, polishing and improving the user interface to make our users happy, not only about the services we provide, but also about the look and feel of the app in general. At the end of the day, you don’t go to your first date or an interview in your pyjamas, but instead you would make sure that you wear a suit, or at least something smart/casual and presentable.

First, I want to mention that in Badoo we prefer to build UI in the code. This approach has its own pros and cons, but it’s not the topic of this post. Today I want to talk about building custom UI components, which is tightly coupled with the opposite approach of building UI — via Interface Builder (IB). Depending on your project, you may want to have some custom reusable UI components to be available for you in IB, to play with your UI component parameters without compiling the project and so on. And here I’m going to show you how to achieve that.

You can check out the full source code of the example project here, or just create an empty project of your own to follow up with the steps below. However, I will be skipping the code snippets for views creation and constraints, so the full source code is worth checking.

The idea

Let’s create a simple UI component for our example app to present some information text. The component should reveal a link when a user taps on it. It should have some basic IB configurable properties like border style, texts, colours, and so on.

Designable class

It’s very simple. To create a custom component you just need to create a new class, extend it from UIControl (in our example I extended from UIView for simplicity) and add @IBDesignable annotation:

Then add your inspectable properties [a property which a user of your component can change in IB]:

Using your component in IB

Now, it’s time to test this new UI component in IB. To do so, just drag&drop a “view” from the IB Object library to the main view and then add minimal constraints such as position, width, height:

Then set the UIView’s custom type to the one we created before, i.e. MyDesignableComponent:

And voilà! Now we can see borderWidth property within our view’s properties in the Attributes Inspector:

You probably noticed that if you change a value of borderWidth in IB it won’t do anything, and that’s because we didn’t bind any logic to it, so let’s fix that and update borderWidth property implementation in the code to the following:

Now compile the project, open IB and try to change the borderWidth property to some positive number — there you go! Now the border is visible:

In similar way we can add more properties like border colour:

We also can add some text properties with a default values like this:

Simple, isn’t? And that’s pretty much it!

Now, after just a few more minutes of work we have a component like this:

And here’s what this component configuration looks in IB:

Some tips

Sometimes you may need to have an inspectable property for UI designing only, for example you want to see what the “expanded state” of your control will look like in IB. In order to achieve that, you need to wrap the block of code in the preprocessor macro #if TARGET_INTERFACE_BUILDER .. #endif

As an option, it’s also possible to prepare your custom UI control specifically for IB by overriding the prepareForInterfaceBuilder method in your class.

And never forget to update the related view’s state upon @IBInspectable property change to see the result in IB right away, like we did in the borderWidth and borderColor didSet implementations.

Limitations

Designable components have some limitations. For example, you can only mark a limited set of types as @IBInspectable, which means you cannot have an inspectable enum or array of Strings property.

Another potential downside of @IBDesignable components is that in order to reflect the latest changes in a designable component’s implementation, a project rebuild is required (Xcode does this automatically in the background). So, this could be a decisive factor for big projects. A fair solution for this issue might be a separate project for UI components.

Designable components are not limited by UIView, and again, you can extend from UIControl and take full control of your component’s rendering and laying out.

Conclusions

In general, I think UIKit gives developers a lot of flexibility in implementing UI. For instance, @IBDesignable components could simplify UI development as they give a developer the ability to set up UI in Storyboard, playing with various parameters without recompiling a project.

So, depending on your workflow and needs, I think, this approach might be useful for you, but if not — no problem, at least you know your options!

Thanks for reading!

Cheers.

Resources

The full project is available here: https://github.com/chupakabr/DesignableComponentExample

Detailed reference by Apple: https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/ImplementingACustomControl.html

Preparation of UI for IB: https://developer.apple.com/documentation/objectivec/nsobject/1402908-prepareforinterfacebuilder

What’s new in Xcode 6: https://developer.apple.com/videos/play/wwdc2014/401/

--

--