Search code examples
iosswiftuikituilabelnsattributedstring

NSAttributedString - Underline colors are not applied correctly


I want to underline and color a text in an UILabel. The underline and the text have a complex pattern of changing colors, but my code sometimes fails.

The following minimal code reproduces the issue.

        let attributedTitle = NSMutableAttributedString(string: "ABC")

        attributedTitle.addAttributes([
            .foregroundColor: UIColor.black,
            .underlineColor: UIColor.black,
            .underlineStyle: NSUnderlineStyle.single.rawValue,
        ],
        range: NSRange(location: 0, length: 1))

        attributedTitle.addAttributes([
            .foregroundColor: UIColor.yellow,
            .underlineColor: UIColor.yellow,
            .underlineStyle: NSUnderlineStyle.single.rawValue,
        ],
        range: NSRange(location: 1, length: 1))

        attributedTitle.addAttributes([
            .foregroundColor: UIColor.black,
            .underlineColor: UIColor.black,
            .underlineStyle: NSUnderlineStyle.single.rawValue,
        ],
        range: NSRange(location: 2, length: 1))

        let label = UILabel()
        label.attributedText = attributedTitle

It shows this.

I expected this. I photoshopped it to show what I expected :(

How to underline and color the text that I expected?


Solution

  • Noticed that this happens when you have the same UIColor for the first and third characters. But not sure why this happens. As a workaround, you could create a new UIColor equal to UIColor.black for the third character as below

    let attributedTitle = NSMutableAttributedString(string: "ABC")
    
    attributedTitle.addAttributes([
        .foregroundColor: UIColor.black,
        .underlineColor: UIColor.black,
        .underlineStyle: NSUnderlineStyle.single.rawValue,
    ],
    range: NSRange(location: 0, length: 1))
    
    attributedTitle.addAttributes([
        .foregroundColor: UIColor.systemYellow,
        .underlineColor: UIColor.systemYellow,
        .underlineStyle: NSUnderlineStyle.single.rawValue,
    ],
    range: NSRange(location: 1, length: 1))
    
    attributedTitle.addAttributes([
        .foregroundColor: UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0),
        .underlineColor: UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0),
        .underlineStyle: NSUnderlineStyle.single.rawValue,
    ],
    range: NSRange(location: 2, length: 1))