Skip to content

Instantly share code, notes, and snippets.

@eastari
Created May 25, 2020 13:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eastari/cf139774fbaf6e26b5c5034a25a695d0 to your computer and use it in GitHub Desktop.
Save eastari/cf139774fbaf6e26b5c5034a25a695d0 to your computer and use it in GitHub Desktop.
func generateUnderlineUnicodeText(from attributedString: NSAttributedString, by key: NSAttributedString.Key) -> String {
var keyRanges = [NSRange]()
// Find all attributes by difference (key) and take ranges
attributedString.enumerateAttributes(in: NSRange(location: 0, length: attributedString.length)) { (attributes, range, _) in
attributes.forEach { (key, value) in
switch key {
case key: keyRanges.append(range)
default: print("Unknown attribute found in the attributed string")}
}
}
var resultString = attributedString.string
// Replace characters on the same underlined
keyRanges.forEach { range in
let stringForMutation = attributedString.attributedSubstring(from: range).string
guard let underlineUnicodeText = stringForMutation.underlineUnicode, stringForMutation.count == underlineUnicodeText.count else {
fatalError("Error - underlineUnicodeText, unowned symbols or length not same")
}
// The reason is that the range points of underline unicode text stored as a UTF-8 surrogate pair.
// We have to count the additional characters for the right range definition.
let extraSymbolsCount = (resultString.utf8.count - attributedString.string.utf8.count) / 2
let range = NSRange(location: range.location + extraSymbolsCount, length: range.length)
guard let swiftRange = Range(range, in: resultString) else {
fatalError("Error - Range conflict")
}
resultString.replaceSubrange(swiftRange, with: underlineUnicodeText)
}
return resultString
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment