I have user input which can contain markdown or not. I want to show the user input on screen with rendered markdown. For some reason, I want to add my own static string which does not contain markdown to the end of the user input in the blue color.
It worked when I didn't used markdown. My guess is that Data
is changing the original range, which makes my code invalid.
This is my code:
let trailing = "I MUST be blue :)"
let newString = "some *user* input" trailing
let data = newString.data(using: .utf8)!
let replacedMessageText = try! NSMutableAttributedString(markdown: data)
replacedMessageText.addAttribute(
NSAttributedString.Key.foregroundColor,
value: UIColor.blue,
// Here I want to find the range of my trailing static text
range: (newString as NSString)
// This line is probably wrong...
.range(of: trailing, options: .backwards)
)
This crashes with this error:
"NSMutableRLEArray objectAtIndex:effectiveRange:: Out of bounds"
I did check out the methods on Data
, but none of them returns an NSRange
. How can I make my code work? Markdown does not support colored text :(.
CodePudding user response:
For clarity of the explanation, let's do a little change:
let trailing = "I MUST be blue :)"
let newString = "some *user* input" trailing
->
let trailing = "I MUST be blue :)"
let leading = "some *user* input"
let newString = leading trailing
The issue is that newString
is different from replacedMessageText.string
, because the Markdown tags (here it's *
) have been interpreted and removed. You can see it by printing replacedMessageText.string
.
So in your case, the range of the trailing is wrong (it's length is too big), hence the error.
If you had reversed trailing
and leading
, it would have worked with your sample case, but you would have seen part of leading
colored.
Instead, you can do:
let final = NSMutableAttributedString()
let leadingAttrStr = try NSAttributedString(markdown: Data(leading.utf8))
let trailingAttrStr = NSAttributedString(string: trailing, attributes: yourBlueAttributes)
final.append(leadingAttrStr)
final.append(trailingAttrStr)
As a note (it's not your case, but if someone encounter the issue), if you have a Markdown tag that starts on leading
and ends on trailing
, it won't be rendered.
Unrelated:
newString.data(using: .utf8)!
can be done with Data(newString.utf8)
, no need to force unwrap.