Given a string, The * quick * brown * fox * jumps * over * the * lazy * dog
, I'm applying font modifiers as follows in order to style all occurrences of asterisk differently than the rest of the text.
func customDesc(_ text: String) -> NSMutableAttributedString {
let asteriskTextRange = (text as NSString).range(of: "*")
let attributedString = NSMutableAttributedString(string: text, attributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 15, weight: .semibold)])
attributedString.setAttributes([NSAttributedString.Key.font : UIFont.systemFont(ofSize: 20, weight: .heavy)], range: asteriskTextRange)
return attributedString
}
It seems range(of:)
will only pick the first occurrence so how do update all occurrences and display the resultant text in a Text
view? I could not find any initialisers that accept NSMutableAttributedString
. Any help is appreciated.
Text
s take the Swift AttributedString
s instead of the NSAttributedString
s from Objective-C. You can convert to AttributedString
simply by using one of its initialisers.
Text(AttributedString(customDesc(...)))
However, I would suggest that customDesc
return a AttributedString
directly, as it is more Swifty. You can use ranges(of:)
to find all the ranges of a particular substring.
func customDesc(_ text: String) -> AttributedString {
var attributedString = AttributedString(text)
attributedString.font = Font.system(size: 15, weight: .semibold)
for range in text.ranges(of: "*") {
// this converts Range<String.Index> to Range<AttributedString.Index>
if let lowerBound = AttributedString.Index(range.lowerBound, within: attributedString),
let upperBound = AttributedString.Index(range.upperBound, within: attributedString) {
let attrRange = lowerBound..<upperBound
attributedString[attrRange].font = Font.system(size: 20, weight: .heavy)
}
}
return attributedString
}
Text(customDesc(...))