Ensuring that applications remain accessible for all is one of our highest priorities at Livefront, and we believe that a key component in achieving that goal is to flawlessly support Dynamic Type in all of our applications. Part 1 of our Practical Dynamic Type series focused on supporting iOS 10 and Part 2 focused on unit testing. This third installment will focus on Attributed Strings.
You can access the complete demo app for this article, here.
You may be asking: “Isn’t there already
adjustsFontForContentSizeCategory?” You’re right! Setting aside for a moment the fact that it is not unit testable (as discussed in Part 2), let’s see what happens when we assign an Attributed String to an
adjustsFontForContentSizeCategory = true.
On iOS 11 and above, everything works as expected
But, on iOS 10, an
AttributedString in an
UILabel does not respond to
Let’s fix this
First, let’s define a
UIView that hosts a
UILabel displaying multiple attributed strings:
Second, let’s hook into
Whereas we’ve been able to set the font size property on the entire
UILabel inside the
uiContentSizeCategoryChanged() before, now we will have to set the type size on each individual formatted segment within the
AttributedString as each formatting segment may have different type size. Therefore, in response to
ContentSizeCategoryDidChange, we will have to enumerate through each formatting segment of the overall
AttributedString and update each formatted segments’ type sizes.
Let’s first enumerate over the
AttributeString to access each of the four sub-attributed strings we created above:
In order to calculate the new type sizes, we will need to have separate
FontSetter closures that the enumeration block in
can use on each attributed substring (see lines 11, 20, 31, and 40
below). This allows the individual attributed substring to get its type
size regenerated with its own
And now, all we have to do is get a new
UIFont with updated sizes by re-executing the
FontSetter closure for each substring and then assigning those new fonts to the preexisting string:
Using this technique, it is possible to unit test the Dynamic Type
pointSize as well!
Which, as expected, passes!
Now, you can support Dynamic Type with
AttributedString on pre-iOS 11 devices, and unit test it, too! 🍰
You can access the complete demo app for this article here. (Please note that Neutraface Slab Text font shown throughout the article is not included, and it has been replaced with Courier.)
Keehun finds ways to unit test everything at Livefront.