Let’s think like a developer and start to decompose the view into smaller components. As an example, we could say:

Your Birthdate View , composed of 2 different UILabels, aligned vertically, the one in the top with bold font and the one in the bottom with normal font. Both UILabels use the whole width and they are left aligned.

, composed of 2 different UILabels, aligned vertically, the one in the top with bold font and the one in the bottom with normal font. Both UILabels use the whole width and they are left aligned. Favorite Music View, composed by an UIImageView in the top and centered and an UILabel centered as well that use the whole width.

composed by an UIImageView in the top and centered and an UILabel centered as well that use the whole width. Friend Request View, composed by probably 2 UILabels in the top, the first one with a single line and bold, the second one multiline. Then, above in the left an UIImageView with right padding, and finally we have another UILabel that uses the remaining width.

This could be an approach taken by someone that doesn’t know in depth the power of some UI elements. So, it implies that most probably the developer will create 3 different layouts to implement the 3 different views. It for sure will work but, as a result, it will finish having a lot of code and most probably a frustrated developer.

What are the alternatives then?

In this case, we are so lucky, the simplest solution as possible is the best one. It just needs one single view composed of a singe UILabel:

Very generic UITableViewCell composed by a single UILabel

Discovering the power of the NSAttributedString

Every single UILabel contains a property called attributedText, this property expects to receive an object of NSAttributedString type.

Following the official Apple documentation, we have:

An NSAttributedString object manages character strings and associated sets of attributes (for example, font and kerning) that apply to individual characters or ranges of characters in the string. An association of characters and their attributes is called an attributed string. The cluster’s two public classes, NSAttributedString and NSMutableAttributedString , declare the programmatic interface for read-only attributed strings and modifiable attributed strings, respectively.

Basically, the NSAttributedString is the best option to generate rich text. Is easy to customize and it allows hundred of possibilities.

Simplify the layout

The rending of views is one of the most expensive operations in iOS Development. That why is essential to reuse elements in run-time and reduce the layout complexity.

With the solution that we just took, we have a Win-Win. We are going to make use of a UITableViewCell which by nature is a reusable component and then inside we are going to have a single UILabel that fill to the parent container using AutoLayout.

Layout composition of the generic UITableViewCell with one single UILabel

Before to continue I heavily recommend you to take a look at my previous article Speed Up your iOS Development: The Modules’s Paradigm (part 1). Because from this point till the end we are to follow and use the examples previously described there.

Reuse the same layout along with multiples views

Although looks incredible, to fulfill the requirements from the original designs, taking the advantages of the NSAttributedString we just need to set 2 different values: backgroundColor and myLabel.attributedText.

In order to make easier to configure the view, let’s create a specific model that will contain all the information requested from the view layout. This is when the Decorator start to play.

Decorator

The Decorator is just like a simple ViewModel object that is used to “Decorate the view” (please don’t confuse with the Decorator pattern).

How we pretend to reuse the same layout to create 3 different views, we are going to call to our Decorator class, CommonAttributedDecorator.

As you can notice, the CommonAttributedDecorator just return 2 values, backgroundColor, and attributedTitle. Exactly the same values that the main view layout was demanding.

Next step is to prepare the generic view layout that will use the decorator. We just need an UITableViewCell called AttributedCell:

So far, everything looks so easy. But, wait for a moment…

Where is the complexity that views require?

The response is easy — everything is in the subclasses of the CommonAttributedDecorator. There we will override the backgroundColor, and attributedTitle methods to satisfice the designs.

Move the logic as much as you can to the Decorator

The Decorators have the ownership to contain the whole design logic as:

- Font Color/Size

- Icons

- Alignments

- Constrain values

And they also include some business logic, like translations or elements that are presented/hidden depending on some business conditions.

Next, we have the decorator used for the Your Birthdate View, BirthdateAttributedDecorator.

The above image just shows the public exposed functions, however, as you can notice we are calling some internal functions as mainAttributedInfo , attributedBreakLine , descAtreibutedInfo and lightColor . They are described in the same file as a private extension:

Here we have several properties, where we define all the business & design logic squeezing to the maximum the NSAttributedString power.

Please, take a look at the methods and you will quickly understand how NSAttributedString works.

The same applies to the Favorite Music View, using the FavoriteMusicAttributedDecorator.

And the additionals private properties:

And finally, the Friend Request View, creating the RequestFriendsAttributedDecorator:

And it owns private properties.

In general, the complexity of the Decorator depends directly on the complexity of the view. The more different colors, font size, and styles it has, the more programmatically code it will require.

Final Results

We are going to implement a new Module with a single reusable AttributedCell . Here we are the AttributedModule.

As you can notice, we are customizing the AttributedCell view passing by parameter the Decorator to use:

attributedCell.configure(decorator: decorator)

Easy right? with just a single method, we are setting up what view is going presented.

Finally, this is how the 3 different rows look like