'NSAttributedString with baselineOffset can cause the last line to be cut off

I’ve got an attributed string with a set baseline offset which renders as I’d expect.

enter image description here

The issue is when I add any other style (color, strikethrough, link, etc) to only part of the string, the text gets positioned wrong so that the last line isn’t rendered.

enter image description here

Is there a way to make this work properly?

My original goal was to change the line height to be smaller than the default of the font, then move the baseline so the tops of some characters wont be cut off (like $).


Here's the simplest version I could make to reproduce this in a playground.

import UIKit
​
let baselineOffset: Float = 5
​
let defaultAttributes: [NSAttributedString.Key: Any] = [
    .baselineOffset: NSNumber(value: baselineOffset),
]
​
let middleAttributes: [NSAttributedString.Key: Any] = [
    .foregroundColor: UIColor.blue,
//    .strikethroughStyle: NSNumber(value: NSUnderlineStyle.single.rawValue)
//    .link: URL(fileURLWithPath: ""),
]
​
let part = NSMutableAttributedString(string: "Lorem ipsum\n", attributes: defaultAttributes)
​
let middlePart = NSMutableAttributedString(attributedString: part)
middlePart.addAttributes(middleAttributes,
                          range: NSRange(location: 0, length: middlePart.length))
​
let string = NSMutableAttributedString()
string.append(part)
string.append(middlePart)
string.append(part)
​
// Remove last newline
string.replaceCharacters(in: NSRange(location: string.length-1, length: 1), with: "")
​
print(string)
​
let label = UILabel()
label.backgroundColor = .white
label.numberOfLines = 0
label.attributedText = string
label.sizeToFit()
label


Solution 1:[1]

The problem is that the baselineOffset value is greater than the text height, it's above or below the text size frame, depending on the value. Try to adjust the baselineOffset value.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1