What are Character and Run in 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.
- Characters provides access to the string.
- 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.
You can easily support sarunw.com by checking out this sponsor.
Localization Buddy: Easiest way to localize and update App Store metadata.
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.
// 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.
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.
- The first, where the foreground is not set (
nil
). - The second where the foreground is set to pink color.
- The third, where it is not set again.
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 ShareHow 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.
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.