1

I would like to color the links and give special color to the underline of the links in my text that received from html.

This is what I have at the moment:

...

public func htmlStyleAttributeText(text: String) -> NSMutableAttributedString? {

        if let htmlData = text.data(using: .utf8) {

            let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html, NSAttributedString.DocumentReadingOptionKey.characterEncoding: String.Encoding.utf8.rawValue]

            let attributedString = try? NSMutableAttributedString(data: htmlData, options: options, documentAttributes: nil)

            let attributes: [NSAttributedString.Key: AnyObject] = [NSAttributedString.Key.foregroundColor: UIColor.red]
            attributedString?.addAttributes(attributes, range: NSRange.init(location: 0, length: attributedString?.length ?? 0))
            return attributedString
        }

        return nil
    }
....

This is what I get: enter image description here

What I am looking for is regular color for the text and red for the links and green for the underline of the links

Luda
  • 7,282
  • 12
  • 79
  • 139

2 Answers2

5

The color for the text is red because you set it to red for the entire attributed string:

let attributes: [NSAttributedString.Key: AnyObject] = 
                  [NSAttributedString.Key.foregroundColor: UIColor.red]
attributedString?.addAttributes(attributes, 
                  range: NSRange.init(location: 0, length: attributedString?.length ?? 0))

If you want it to have a "regular" (= I guess black?) color, just don't do that and delete those lines.

And here's how to set the color for the links in your attributed string:
Change the color of a link in an NSMutableAttributedString

This is the key you'll need to use for setting a different underline color:
NSAttributedString.Key.underlineColor


Edit:

To make it more explicit and put the pieces together — this is what you have to do in order to yield the desired link colors:

textView.linkTextAttributes = [
    .foregroundColor: UIColor.black,
    .underlineColor: UIColor.red
]

(In addition to removing to two lines of code as stated above.)

Mischa
  • 15,816
  • 8
  • 59
  • 117
  • But I do not know what is the range of the links? – Luda Mar 20 '19 at 16:10
  • @Luda I showed on another question how to get the .link ranges: https://stackoverflow.com/questions/55249765/how-can-i-append-value-if-nsattributedstring-contains-external-link/55259853#55259853 – Larme Mar 20 '19 at 16:12
  • You don't need to. You just set the [link attributes](https://developer.apple.com/documentation/uikit/uitextview/1618632-linktextattributes) for your entire text view: `textView.linkTextAttributes = ...`. – Mischa Mar 20 '19 at 16:12
  • It works. All underlines were colored in red. But the links text are still blue. – Luda Mar 20 '19 at 16:13
  • So is that what you wanted? – Mischa Mar 20 '19 at 16:16
  • @Mischa black text, red underline – Luda Mar 21 '19 at 06:57
  • It’s all included in the other answer I linked above: You only have to set the respective color for the right attribute keys. For the underline color, you use the key ‘NSAttributedString.Key.underlineColor’, for the font color, you use the key ‘NSAttributedString.Key.foregroundColor’. And then you assign those values to the property ‘linkTextAttributes’. – Mischa Mar 21 '19 at 07:08
  • (See the additions to my answer above.) – Mischa Mar 21 '19 at 07:16
  • Foreground color doesn't help. The link will stay blue. I needed to update the tint color to black and then it worked. – Luda Mar 21 '19 at 11:23
  • I have tested the above code. For me, it works exactly as described. The `foregroundColor` sets the color of the text itself. Maybe there is some other code in your project that overrides this attribute at some point? – Mischa Mar 21 '19 at 11:47
1

If you are using a UITextView, it would be enough to set the tintColor to UIColor.red and remove the following:

let attributes: [NSAttributedString.Key: AnyObject] = [NSAttributedString.Key.foregroundColor: UIColor.red]
attributedString?.addAttributes(attributes, range: NSRange.init(location: 0, length: attributedString?.length ?? 0))

so it would look like this:

public func htmlStyleAttributeText(text: String) -> NSMutableAttributedString? {
    if let htmlData = text.data(using: .utf8) {
        let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html, NSAttributedString.DocumentReadingOptionKey.characterEncoding: String.Encoding.utf8.rawValue]
        let attributedString = try? NSMutableAttributedString(data: htmlData, options: options, documentAttributes: nil)
        return attributedString
    }
    return nil
}

//
textView.tintColor = .red
textView.attributedText = htmlStyleAttributeText(text: "random text <a href='http://www.google.com'>http://www.google.com </a> more random text")

Output: enter image description here

Omar Chaabouni
  • 448
  • 2
  • 19
  • Thank you Omar, Can you please make the text black? – Luda Mar 21 '19 at 06:58
  • I got it! Red underline and black tintcolor – Luda Mar 21 '19 at 07:36
  • @Luda: How did you achieve a different underline and text color using the ‘tintColor’ property? That property should affect both colors... – Mischa Mar 21 '19 at 11:12
  • @Mischa NSAttributedString.Key.underlineColor: UIColor.red – Luda Mar 21 '19 at 11:21
  • Omar and @Mischa, It would be great if you could take a look at this question (which is in the same field) https://stackoverflow.com/questions/55279279/crashing-on-range-on-nstextstorage – Luda Mar 21 '19 at 11:22
  • @Luda: Then you’re not using the ‘tintColor’ because that’s an attribute, right? – Mischa Mar 21 '19 at 11:24
  • @Mischa you can set the tint color in code like this: textView.tintColor = .black or in the storyboard. – Luda Mar 21 '19 at 11:27
  • I know how to set the tint color. I only want to make sure that other Stackoverflow users with the same problem as you find the correct answer and know what to do. Plus, I was also curious how this alternative solution might work. As you have marked this answer as the correct one, it should be clear for others what to do and for me, it just wasn't. Now – I believe – it is: You're using a combination of both answers. – Mischa Mar 21 '19 at 11:55