使用旧金山字体将 HTML 解析为 NSAttributedString? (iOS 9)

Parse HTML into NSAttributedString with San Francisco Font? (iOS 9)

我需要解析包含 <b>(粗体)、<i>(斜体)和 <u>(下划线)标记的基本 HTML 字符串,仅此而已那些简单的标签。

现在,当在 iOS 9 中使用新的 San Francisco 时,我只能让 <u>(下划线)标签在 NSAttributedString 中正确呈现。

我真的需要 <b>(粗体)和 <i>(斜体)来渲染。

这是我正在做的事情:

let text = "<i>Any</i> <b>Text</b> <u>that's basic HTML</u>"
let font = UIFont.preferredFontForTextStyle(UIFontTextStyleBody)

let modifiedFont = NSString(format:"<span style=\"font-family: '-apple-system','HelveticaNeue'; font-size: %f \">%@</span>",
font.pointSize, text) as String

let data = (modifiedFont as NSString).dataUsingEncoding(NSUTF8StringEncoding)

let attributedString = try? NSAttributedString(data: data!, options:
            [ NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType,
                NSCharacterEncodingDocumentAttribute : NSUTF8StringEncoding,
                NSFontAttributeName : font ],
            documentAttributes: nil)

但不幸的是,<i>(斜体)和 <b>(粗体)标签从未呈现,只有 <u>(下划线)正确呈现。

同样的方法也适用于 iOS 8Helvetica-Neue 字体,但不适用于新的 iOS 9 San Francisco 字体

帮我让 <b>(粗体)和 <i>(斜体)在 NSAttributedString!

中正确呈现

更新:我也在整个应用程序中使用动态文本。这可能是无法正常工作的原因...

在应用中同时使用 NSAttributedStringDynamicType 是导致问题的原因。

事实证明,在收到 UIContentSizeCategoryDidChangeNotification 后,您 需要 到 re-parse/render 您的 String。您不能保留 NSAttributedString 然后用它来重置 UILabel 中的文本。您必须 re-parse/render NSAttributedString.

简要示例:

public override func viewDidLoad() {
    super.viewDidLoad()

    //register be notified when text size changes.
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("didChangePreferredContentSize:"), name: UIContentSizeCategoryDidChangeNotification, object: nil)
}

// The action Selector that gets called after the text size has been changed.
func didChangePreferredContentSize(notification: NSNotification) {
    self.myLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
    //
    // DO NOT do this:
    // self.myLabel.attributedText = self.myAlreadyRenderedText
    //
    //Make sure you re-render/parse the text into a new NSAttributedString.
    //Do THIS instead:
    self.myLabel.attributedText = self.renderAttributedText(str)
}

//Our method to render/parse the HTML tags in our text. Returns an NSAttributedString.
func renderAttributedText(str: String) -> NSAttributedString? {
    let text = "<i>Any</i> <b>Text</b> <u>that's basic HTML</u>"
    let font = UIFont.preferredFontForTextStyle(UIFontTextStyleBody)

    let modifiedFont = NSString(format:"<span style=\"font-family: '-apple-system','HelveticaNeue'; font-size: %f \">%@</span>",font.pointSize, text) as String

    let data = (modifiedFont as NSString).dataUsingEncoding(NSUTF8StringEncoding)

    let attributedString = try? NSAttributedString(data: data!, options:
        [ NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType,
            NSCharacterEncodingDocumentAttribute : NSUTF8StringEncoding,
            NSFontAttributeName : font ],
        documentAttributes: nil)

    return attributedString
}

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}