Add image to UILabel with Swift (iOS)

This week while working on one of our client apps I came across interesting problem of embedding images with text. To give a little idea, we wanted to display text somewhat like emojis embedded in the message.

Doesn't that look cool? It definitely does. Initially I drew the conclusion of this task being impossible or another ugly hack to arrange UILabel and UIImageView side by side. Ewww! I know. I didn't go that way though.

A quick Google search took me to StackOverflow page on How to embed small icon in UILabel

Here, we will try to replicate following emoji message with Swift.

In order to do it, we will need two utilities,

  1. NSTextAttachment (From UIKit)
  2. NSMutableAttributedString (From Foundation)

I am going to do everything programmatically. So please bear with me.

First off, let create an instance of UILable to display on viewport and assign required properties and set of constraints

let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
self.view.addSubview(label)
label.font = UIFont.systemFontOfSize(22)
let views = ["label": label]
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[label]-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views))
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-44-[label]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views))

This label will be used to create our interactive text with funny emojis.

Next, let's create a collection of emoji UIImages and default icon sizes to use. Here we will have 5 emoji images as follows,

  1. Love
  2. Jeans
  3. Fire
  4. Dash
  5. Baby
let iconsSize = CGRect(x: 0, y: -5, width: 30, height: 30)
let emojisCollection = [UIImage(named: "love"), UIImage(named: "jeans"), UIImage(named: "fire"), UIImage(named: "dash"), UIImage(named: "baby")]

Now let's start creating our NSMutableAttributedString and related text attachments.

In a nutshell we are going to follow steps below,

Instantiate the NSMutableAttributedString

let attributedString = NSMutableAttributedString(string: "Your ")

Attach necessary NSAttributedString is applicable

attributedString.appendAttributedString(NSAttributedString(string: " was holdin'\n"))
        attributedString.appendAttributedString(NSAttributedString(string: "Ripped "))

Attach image to the attributed string

let attachment = NSTextAttachment()
attachment.image = emojisCollection[1]
attachment.bounds = UIImage(named: "jeans") attributedString.appendAttributedString(NSAttributedString(attachment: attachment))

We are going to repeat the similar code to create rest of our custom Attributed string and assign it to our label at the end.

let attributedString = NSMutableAttributedString(string: "Your ")

let loveAttachment = NSTextAttachment()
loveAttachment.image = emojisCollection[0]
loveAttachment.bounds = iconsSize
attributedString.appendAttributedString(NSAttributedString(attachment: loveAttachment))

attributedString.appendAttributedString(NSAttributedString(string: " was holdin'\n"))
attributedString.appendAttributedString(NSAttributedString(string: "Ripped "))

let jeansAttachment = NSTextAttachment()
jeansAttachment.image = emojisCollection[1]
jeansAttachment.bounds = iconsSize
attributedString.appendAttributedString(NSAttributedString(attachment: jeansAttachment))

attributedString.appendAttributedString(NSAttributedString(string: " ,\n"))
attributedString.appendAttributedString(NSAttributedString(string: "skin was showin'\n"))

let fireAttachment = NSTextAttachment()
fireAttachment.image = emojisCollection[2]
fireAttachment.bounds = iconsSize
attributedString.appendAttributedString(NSAttributedString(attachment: fireAttachment))

attributedString.appendAttributedString(NSAttributedString(string: " night, wind was "))

let dashAttachment = NSTextAttachment()
dashAttachment.image = emojisCollection[3]
dashAttachment.bounds = iconsSize
attributedString.appendAttributedString(NSAttributedString(attachment: dashAttachment))

attributedString.appendAttributedString(NSAttributedString(string: "\nWhere you think\n"))
attributedString.appendAttributedString(NSAttributedString(string: "you're going, "))

let babyAttachment = NSTextAttachment()
babyAttachment.image = emojisCollection[4]
babyAttachment.bounds = iconsSize
attributedString.appendAttributedString(NSAttributedString(attachment: babyAttachment))

attributedString.appendAttributedString(NSAttributedString(string: " ?"))
    
label.attributedText = attributedString

And that's it. Boom! The result of our code is visible below. (Taken directly from the simulator)

Isn't it just awesome? Now you can also use emojis with text to create interactive app experience using this simple trick. Source code is Hosted on Github