Suppose I have a configuration-based button, with an attributed title:
let button = UIButton(configuration: .plain())
let font = UIFont(name: "Georgia", size: 16)
button.configuration?.attributedTitle = AttributedString(
"Hello", attributes: AttributeContainer.font(font!)
)
If I later come along and set the configuration’s title to a different title, the attribute information is lost. For example:
button.configuration?.title = "Goodbye"
// Button title is no longer in Georgia font!
What I want to do here is to replace the text of an attributed string title without disturbing its attributes. But Swift’s AttributedString doesn’t seem to provide a way to do that. What’s the correct approach here?
2
Answers
Changing the text of an AttributedString is remarkably tricky. You have to replace the contents of the attributed string's character view — its
characters
property. To make things even harder, you cannot do this simply by assigning another string! For example, this won't compile:Nor is it sufficient to derive the character view from a simple string. This doesn't compile either:
This is because the separate character view of a simple string no longer exists; you're still trying to assign a String into a character view, and we already know you can't do that.
Instead, you can make another AttributedString and assign its character view into the button's attributed title's character view:
That replaces the button's title without disturbing the button's title's style attributes. This is such a useful thing to be able to do that I've made a little utility extension on UIButton that covers all the cases:
If the attributes of your title will always apply to the entire title then an alternate approach is to use the
titleTextAttributesTransformer
property of the button configuration instead of making use ofattributedTitle
. Then you can simply change the button’s title and those attributes will be applied to the whole title.For example:
Then later you can simply do:
and the new title will have the same font and other attributes of the original title.