Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
381 views
in Technique[技术] by (71.8m points)

ios - Swift- Change font on an HTML string that has its own Styles

I am dinamically getting an HTML string from a Wordpress API and parsing it into an Attributed String to show it in my app. Since the string has its own styles, it shows different fonts and sizes, something that is affecting our design choices.

What I want to do is change the font and its size on the whole attributed string.

I tried doing so in the options of the attributed string, but it does nothing:

let attributedT = try! NSAttributedString(
            data: nContent!.decodeHTML().data(using: String.Encoding.unicode, allowLossyConversion: true)!,
            options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSFontAttributeName: UIFont(name: "Helvetica", size: 16.0)!],
            documentAttributes: nil)
        contentLbl.attributedText = attributedT

Does anybody have any ideas on how to achieve this?

P.S. I know that I could add a CSS tag to the beginning or end of the string, but would this override other styles in it? Also, if this is a valid solution, could you please provide a sample on how to do it?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Swift 4 solution


  • NSAttributedString extension with convenience initializer
  • Enumerates through the attributed string (HTML document) font attributes, and replaces with the provided UIFont
  • Preserves original HTML font sizes, or uses font-size from provided UIFont, @see useDocumentFontSize parameter
  • This method can simply convert HTML to NSAttributedString, without the overload of manipulating with fonts, just skip the font parameter, @see guard statement

extension NSAttributedString {

    convenience init(htmlString html: String, font: UIFont? = nil, useDocumentFontSize: Bool = true) throws {
        let options: [NSAttributedString.DocumentReadingOptionKey : Any] = [
            .documentType: NSAttributedString.DocumentType.html,
            .characterEncoding: String.Encoding.utf8.rawValue
        ]

        let data = html.data(using: .utf8, allowLossyConversion: true)
        guard (data != nil), let fontFamily = font?.familyName, let attr = try? NSMutableAttributedString(data: data!, options: options, documentAttributes: nil) else {
            try self.init(data: data ?? Data(html.utf8), options: options, documentAttributes: nil)
            return
        }

        let fontSize: CGFloat? = useDocumentFontSize ? nil : font!.pointSize
        let range = NSRange(location: 0, length: attr.length)
        attr.enumerateAttribute(.font, in: range, options: .longestEffectiveRangeNotRequired) { attrib, range, _ in
            if let htmlFont = attrib as? UIFont {
                let traits = htmlFont.fontDescriptor.symbolicTraits
                var descrip = htmlFont.fontDescriptor.withFamily(fontFamily)

                if (traits.rawValue & UIFontDescriptorSymbolicTraits.traitBold.rawValue) != 0 {
                    descrip = descrip.withSymbolicTraits(.traitBold)!
                }

                if (traits.rawValue & UIFontDescriptorSymbolicTraits.traitItalic.rawValue) != 0 {
                    descrip = descrip.withSymbolicTraits(.traitItalic)!
                }

                attr.addAttribute(.font, value: UIFont(descriptor: descrip, size: fontSize ?? htmlFont.pointSize), range: range)
            }
        }

        self.init(attributedString: attr)
    }

}

Usage-1 (Replace font)

let attr = try? NSAttributedString(htmlString: "<strong>Hello</strong> World!", font: UIFont.systemFont(ofSize: 34, weight: .thin))

Usage-2 (NSMutableAttributedString example)

let attr = try! NSMutableAttributedString(htmlString: "<strong>Hello</strong> World!", font: UIFont.systemFont(ofSize: 34, weight: .thin))
attr.append(NSAttributedString(string: " MINIMIZE", attributes: [.link: "@m"]))

Usage-3 (Only convert HTML to NSAttributedString)

let attr = try? NSAttributedString(htmlString: "<strong>Hello</strong> World!")

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...