Search code examples
iosnsattributedstring

Negative baselineOffset values ignored on NSAttributedString (iOS 16.4+ only)


When building for iOS 16.4, we noticed different behavior when it comes to using baselineOffset on an NSAttributedString.

positive values are now handled differently than on previous iOS versions (no need to /2 anymore), but there are already posts talking about that on StackOverflow.

The issue I came across was when using a negative baselineOffset. When used on an NSAttributedString, it works fine, but understandably increases the size of the label.

When used in tandem with NSParagraphStyle's maximumLineHeight and minimumLineHeight, a negative value of baselineOffset is completely ignored.

I used this piece of code to showcase the difference:

        let label1 = UILabel()
        let label2 = UILabel()
        let label3 = UILabel()
        
        self.view.addSubview(label1)
        self.view.addSubview(label2)
        self.view.addSubview(label3)
        
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.minimumLineHeight = 20
        paragraphStyle.maximumLineHeight = 20
        
        let attr1: [NSAttributedString.Key: Any] = [
            .paragraphStyle: paragraphStyle,
            .baselineOffset: 0]
        let attr2: [NSAttributedString.Key: Any] = [
            .paragraphStyle: paragraphStyle,
            .baselineOffset: 5]
        let attr3: [NSAttributedString.Key: Any] = [
            .paragraphStyle: paragraphStyle,
            .baselineOffset: -5]
        
        let str1 = NSAttributedString(string: "0 offset", attributes: attr1)
        let str2 = NSAttributedString(string: "5 offset", attributes: attr2)
        let str3 = NSAttributedString(string: "-5 offset", attributes: attr3)

Notice the difference here between the iOS 16.4 simulator on the left and the iOS 16.2 simulator on the right. positive offset value is doubled on old iOS versions for whatever reason, whereas it's fine on iOS 16.4, but the negative offset value is completely ignored. iOS 16.4 vs iOS 16.2


Solution

  • The issue persists in iOS 16.4 and 16.5 but it is fixed in iOS 16.6 beta 4.

    As mentioned in Release Notes:

    Known Issues

    Starting in iOS 16.6 a negative value for NSBaselineOffsetAttributeName applied to the full run of an attributedText of a UILabel will return to its pre-16.3 behavior of lowering the text position within the label’s bounds. (106109259)

    A stable version of iOS 16.6 is expected to be released in the following days.