What are Character and Run in AttributedString

⋅ 3 min read ⋅ Foundation iOS 15 AttributedString

Table of Contents

An attributed string is a combination of characters, ranges, and attributed values.

The way we can access these values is through "views".

The two important views are characters and runs.

  1. Characters provides access to the string.
  2. Runs provides access to the attributes.

Let's see what the usages of these views are.

Character views

Character view lets you access all characters in an attributed string.

In this example, I find a character "t" and paint it pink.

private var attributedString: AttributedString {
let string = "Attributed String"
var attributedString = AttributedString(string)

attributedString.font = .boldSystemFont(ofSize: 40)

// 1
let characterView = attributedString.characters

// 2
for i in characterView.indices {
// 3
if characterView[i] == "t" {
// 4
attributedString[i..<characterView.index(after: i)].foregroundColor = .pink
}
}

return attributedString
}

var body: some View {
Text(attributedString)
}

1 We get a character view using the characters instance property.
2 We loop over the indices of the character in the attributed string.
3 We check if the character is "t".
4 If it is, we apply foregroundColor = .pink to the range of that character, attributedString[i..<characterView.index(after: i)].

The result is a string with the character "t" in pink.

Character views.
Character views.

You can easily support sarunw.com by checking out this sponsor.

Sponsor sarunw.com and reach thousands of iOS developers.

Run views

A run is a collection of starting location, length, and value of a particular attribute.

It is easier to understand with an example. So, here is a string "Hello, Big Colorful World!" with difference attributed applied.

An attributed string.
An attributed string.
// 1
var fontAttribute = AttributeContainer()
fontAttribute.font = .systemFont(ofSize: 40)

let helloString = AttributedString("Hello, ", attributes: fontAttribute)

// 2
var boldAttribute = AttributeContainer()
boldAttribute.font = .boldSystemFont(ofSize: 40)
let bigString = AttributedString("Big ", attributes: boldAttribute)

// 3
var colorAttribute = AttributeContainer()
colorAttribute.foregroundColor = .pink
colorAttribute.merge(fontAttribute)
let colorString = AttributedString("Colorful ", attributes: colorAttribute)


let worldString = AttributedString("World!", attributes: fontAttribute)

let combination = helloString + bigString + colorString + worldString

1 All characters have the same font size of 40.
2 The string "Big " got a bold font style.
3 The string "Colorful " got a pink color.

This attributed string has four runs.

let runCount = combination.runs.count
// 4

Since a run is a collection of starting location, length, and value of a particular attribute. Each run starts and ends when an attribute changes.

Four runs are separate as follows.

Four runs.
Four runs.

A range from run and character references the same position in the same attributed string, so you can use it interchangeably.

In this example, we get the range of the first runs and get the substring from that range.

let firstRun = combination.runs.first!
print(String(combination.characters[firstRun.range]))
// Hello,

Here is another example where we print out the third run.

let firstIndex = combination.runs.startIndex
let thirdIndex = combination.runs.index(firstIndex, offsetBy: 2)
let thirdRun = combination.runs[thirdIndex]
print(String(combination.characters[thirdRun.range]))
// Colorful

Focus on specific Attribute

A run can view a string over a specific attributed.

That means we might be able to get a different number of runs for the same string.

Here is the example where we focus our run on the foreground attributed.

let runs = combination.runs[\.foregroundColor]
print(runs.count)
// 3

Each element of the resulting collection will focus on the value of the foreground attribute, not taking into account other attributes which may be set in the string.

In this case, we will get three runs instead of four.

  1. The first, where the foreground is not set (nil).
  2. The second where the foreground is set to pink color.
  3. The third, where it is not set again.
Three runs.
Three runs.

Read more article about Foundation, iOS 15, AttributedString, or see all available topic

Enjoy the read?

If you enjoy this article, you can subscribe to the weekly newsletter.
Every Friday, you'll get a quick recap of all articles and tips posted on this site. No strings attached. Unsubscribe anytime.

Feel free to follow me on Twitter and ask your questions related to this post. Thanks for reading and see you next time.

If you enjoy my writing, please check out my Patreon https://www.patreon.com/sarunw and become my supporter. Sharing the article is also greatly appreciated.

Become a patron Buy me a coffee Tweet Share
Previous
How to Hide Toolbar on Scroll in iOS

Since iOS 8, we can easily hide a toolbar when users scroll. Let's learn why and how to do it.

Next
How to fix "You are not authorized to make purchases of this InApp in Sandbox at this time" error

You might encounter this error when testing an In-app purchase in Sandbox mode. Let's learn how to fix it.

← Home