Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I set default font when translating HTML into NSAttributedString?

I'm trying to show HTML in a UILabel, like

NSString * htmlString = @"Some html string \n <font size=\"13\" color=\"red\">This is some text!</font>";

NSAttributedString * attrStr = [[NSAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUnicodeStringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];

And now I get a attributedString

Printing description of attrStr: Some html string

{

...

NSFont = "<UICTFont: 0x7f8240d7c310> font-family: \"Times New Roman\"; font-weight: normal; font-style: normal; **font-size: 12.00pt**";

}

This is some text!

{

...
NSFont = "<UICTFont: 0x7f8240d7aff0> font-family: \"Times New Roman\"; font-weight: normal; font-style: normal; **font-size: 37.00pt**";
}

It seems font-size: 12.00pt is a default-size, I want to change the size without changing the HTML source code. How to do that?

like image 444
Rick Avatar asked Dec 14 '15 09:12

Rick


2 Answers

You can do it with a little bit of coding... You need to go through the attributes and change the font size on each segment of the attributed string (like normal, italic, bold, etc...).

extension String {
    func htmlAttributedString() -> NSMutableAttributedString {

            guard let data = self.data(using: String.Encoding.utf8, allowLossyConversion: false)
                else { return NSMutableAttributedString() }

            guard let formattedString = try? NSMutableAttributedString(data: data,
                                                            options: [.documentType: NSAttributedString.DocumentType.html,
                                                                      .characterEncoding: String.Encoding.utf8.rawValue],
                                                            documentAttributes: nil )

                else { return NSMutableAttributedString() }

            return formattedString
    }

}


extension NSMutableAttributedString {

    func with(font: UIFont) -> NSMutableAttributedString {
        self.enumerateAttribute(NSAttributedStringKey.font, in: NSMakeRange(0, self.length), options: .longestEffectiveRangeNotRequired, using: { (value, range, stop) in
            let originalFont = value as! UIFont
            if let newFont = applyTraitsFromFont(originalFont, to: font) {
                self.addAttribute(NSAttributedStringKey.font, value: newFont, range: range)
            }
        })
        return self
    }

    func applyTraitsFromFont(_ f1: UIFont, to f2: UIFont) -> UIFont? {
        let originalTrait = f1.fontDescriptor.symbolicTraits

        if originalTrait.contains(.traitBold) {
            var traits = f2.fontDescriptor.symbolicTraits
            traits.insert(.traitBold)
            if let fd = f2.fontDescriptor.withSymbolicTraits(traits) {
                return UIFont.init(descriptor: fd, size: 0)
            }
        }
        return f2
    }
}

and you would use it like this

let formattedString = "text  <b>sometext</b>"
                        .htmlAttributedString()
                        .with(font:UIFont(name: "Times New Roman", size: 37)!)
like image 162
Maria Avatar answered Oct 31 '22 03:10

Maria


Here's @Maria's NSMutableAttributedString extension rewritten in Swift 5.1

extension NSMutableAttributedString {

    func with(font: UIFont) -> NSMutableAttributedString {
        enumerateAttribute(NSAttributedString.Key.font, in: NSMakeRange(0, length), options: .longestEffectiveRangeNotRequired, using: { (value, range, stop) in
            if let originalFont = value as? UIFont, let newFont = applyTraitsFromFont(originalFont, to: font) {
                addAttribute(NSAttributedString.Key.font, value: newFont, range: range)
            }
        })

        return self
    }

    func applyTraitsFromFont(_ originalFont: UIFont, to newFont: UIFont) -> UIFont? {
        let originalTrait = originalFont.fontDescriptor.symbolicTraits

        if originalTrait.contains(.traitBold) {
            var traits = newFont.fontDescriptor.symbolicTraits
            traits.insert(.traitBold)

            if let fontDescriptor = newFont.fontDescriptor.withSymbolicTraits(traits) {
                return UIFont.init(descriptor: fontDescriptor, size: 0)
            }
        }

        return newFont
    }
}
like image 27
jonaszmclaren Avatar answered Oct 31 '22 04:10

jonaszmclaren