在iPhone中的UILabel中显示HTML文本

45

我从一个 Web 服务中获取到了 HTML 响应。以下是我收到的 HTML 内容。

<p><strong>Topic</strong>Gud mrng.</p>
\n<p><strong>Hello Everybody</strong>: How are you.</p>
\n<p><strong>I am fine</strong>: 1 what about you.</p>

我需要在UILabel中显示文本。

请帮忙。


使用一个禁用滚动的textView ;) - iOS Flow
11个回答

102

您可以使用属性文本而无需使用任何第三方库来实现此目的。我相信它接受HTML片段,就像您正在获取的那个一样,但是您可能希望将其包装在完整的HTML文档中,以便您可以指定CSS:

static NSString *html =
    @"<html>"
     "  <head>"
     "    <style type='text/css'>"
     "      body { font: 16pt 'Gill Sans'; color: #1a004b; }"
     "      i { color: #822; }"
     "    </style>"
     "  </head>"
     "  <body>Here is some <i>formatting!</i></body>"
     "</html>";

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 300, 200)];
NSError *err = nil;
label.attributedText =
    [[NSAttributedString alloc]
              initWithData: [html dataUsingEncoding:NSUTF8StringEncoding]
                   options: @{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType }
        documentAttributes: nil
                     error: &err];
if(err)
    NSLog(@"Unable to parse label text: %@", err);

虽然不够简洁,但你可以通过为UILabel添加一个类别来整理代码:

@implementation UILabel (Html)

- (void) setHtml: (NSString*) html
    {
    NSError *err = nil;
    self.attributedText =
        [[NSAttributedString alloc]
                  initWithData: [html dataUsingEncoding:NSUTF8StringEncoding]
                       options: @{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType }
            documentAttributes: nil
                         error: &err];
    if(err)
        NSLog(@"Unable to parse label text: %@", err);
    }

@end

[someLabel setHtml:@"Be <b>bold!</b>"];

该方法无法识别 <br> 标签。它只是删除在 <br> 标签前面的元素。 - user2955351
1
在这种情况下,您仍然可以设置字体和颜色吗?self.attributedText = [[NSAttributedString alloc] initWithData: [html dataUsingEncoding:NSUTF8StringEncoding] options: @{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSFontAttributeName:[UIFont fontWithName:@"HelveticaNeue" size:12.0], NSForegroundColorAttributeName: [UIColor redColor] } documentAttributes: nil error: &err]; 似乎不起作用。 - RyanJohnstone
@DemandedCross 我知道你的评论已经很久了,但对于其他人来说,我认为你需要使用HTML颜色代码而不是UIColor。 - Hamzah Malik
sometText<font color=\"#dc2d4e\">372</font> 似乎无法正常工作。 - Zigii Wong
1
在处理CJK字符时,最好使用[html dataUsingEncoding: NSUTF16StringEncoding],因为NSString是UTF16编码的,即NSUnicodeStringEncoding - DawnSong
显示剩余2条评论

17

Swift 4:版本

extension String {
    func htmlAttributedString() -> NSAttributedString? {
        guard let data = self.data(using: String.Encoding.utf16, allowLossyConversion: false) else { return nil }
        guard let html = try? NSMutableAttributedString(
            data: data,
            options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html],
            documentAttributes: nil) else { return nil }
        return html
    }
}

Swift 3:版本

extension String {
func htmlAttributedString() -> NSAttributedString? {
    guard let data = self.data(using: String.Encoding.utf16, allowLossyConversion: false) else { return nil }
    guard let html = try? NSMutableAttributedString(
        data: data,
        options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
        documentAttributes: nil) else { return nil }
    return html
    }
}

Swift 2:版本

extension String {
        func htmlAttributedString() -> NSAttributedString? {
            guard let data = self.dataUsingEncoding(NSUTF16StringEncoding, allowLossyConversion: false) else { return nil }
            guard let html = try? NSMutableAttributedString(
              data: data, 
              options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], 
              documentAttributes: nil) else { return nil }
            return html
        }
}

用法如下:

label.attributedText = yourStringVar.htmlAttributedString()

我的字符串是:“<b>Pro</b>cess Specialist”。但是它返回了我发送给您的扩展相同的东西。 - Mohd Sadham

15
使用RTLabel库将HTML文本转换。我已经多次使用过它,效果很好。以下是该库和示例代码的链接:https://github.com/honcheng/RTLabel。希望这能帮到你。

我面临的一个问题是,在将文本加载到UITableViewCell后,当我旋转设备时,标签文本变得更宽了。在从横向到纵向旋转时也会发生同样的情况,标签文本变窄了。为什么会这样?有什么解决方法吗? - Vaibhav Saran

6

Swift 4

我建议使用可失败的方便初始化来扩展NSAttributedString。 String 的本质并不是创建NSAttributedString

extension NSAttributedString {
     convenience init?(html: String) {
        guard let data = html.data(using: String.Encoding.unicode, allowLossyConversion: false) else {
            return nil
        }
        guard let attributedString = try? NSAttributedString(data: data, options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil) else {
            return nil
        }
        self.init(attributedString: attributedString)
    }
}
label.attributedText = NSAttributedString(html: "<span> Some <b>bold</b> and <a href='#/userProfile/uname'> Hyperlink </a> and so on </span>")

3

DTCoreText 构建时出现编译时错误。报错信息为 'DTHTMLParser.h' 文件未找到。有任何想法吗? - Vaibhav Saran
3
DTCoreTextن»¥ه‰چه¹¶ن¸چوک¯ن¼—و‰€ه‘¨çں¥çڑ„NSAttributedStringم€‚ - William Entriken

2

以下是 Swift 2 版本:

    let htmlStringData = NSString(string: "<strong>Your HTML String here</strong>").dataUsingEncoding(NSUTF8StringEncoding)
    guard let html = htmlStringData else { return }

    do {
        let htmlAttrString = try NSAttributedString(data: html, options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil)
        yourLabel.attributedText = htmlAttrString
    } catch {
        print("An error occured")
    }

1
**// Swift 4 compatible | with setting of colour and font options:**

// add following extension to String:

        func htmlAttributed(family: String?, size: CGFloat, color: UIColor) -> NSAttributedString? {

                let sizeInPx = (size * 0.75)

                do {
                  let htmlCSSString = "<style>" +
                    "html *" +
                    "{" +
                    "font-size: \(sizeInPx)pt !important;" +
                    "color: \(color.hexString ?? "#000000") !important;" +
                    "font-family: \(family ?? "SFUIText-Regular"), SFUIText !important;" +
                  "}</style> \(self)"

                  guard let data = htmlCSSString.data(using: String.Encoding.utf8) else {
                    return nil
                  }

                  return try NSAttributedString(data: data,
                                                options: [.documentType: NSAttributedString.DocumentType.html,
                                                          .characterEncoding: String.Encoding.utf8.rawValue],
                                                documentAttributes: nil)
                } catch {
                  print("error: ", error)
                  return nil
                }
              }

        // add following extension to UIColor:

        extension UIColor{

          var hexString:String? {
            if let components = self.cgColor.components {
              let r = components[0]
              let g = components[1]
              let b = components[2]
              return  String(format: "%02X%02X%02X", (Int)(r * 255), (Int)(g * 255), (Int)(b * 255))
            }
            return nil
          }
        }

    // Sample Use:

    yourLabel.attributedText = locationTitle.htmlAttributed(family: yourLabel.font.fontName,
                                                                           size: yourLabel.font.pointSize,
                                                                           color: yourLabel.textColor)

1

Swift 3中的上述答案:

    var str = "<html> ... some html ... </html>"

    let htmlStringData = NSString(string: str).data(using: String.Encoding.utf8.rawValue)
    let html = htmlStringData

    do {
        let htmlAttrString = try? NSAttributedString(
                data: html!,
                options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
                documentAttributes: nil
        )
        agreementText.attributedText = htmlAttrString
    } catch {
        print("An error occured")
    }

0

Swift 3 中的答案:

func htmlAttributedString() -> NSAttributedString? {
    guard let data = self.data(using: String.Encoding.utf16, allowLossyConversion: false) else { return nil }
    guard let html = try? NSMutableAttributedString(
        data: data,
        options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
        documentAttributes: nil) else { return nil }
    return html
}

0

最近我一直在处理部分HTML片段,并将它们转换为带有添加属性功能的属性字符串。这是我编写的扩展版本:

import Foundation
import UIKit

extension String {
  func htmlAttributedString(attributes: [String : Any]? = .none) -> NSAttributedString? {
    guard let data = self.data(using: String.Encoding.utf16, allowLossyConversion: false) else { return .none }
    guard let html = try? NSMutableAttributedString(
      data: data,
      options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
      documentAttributes: .none) else { return .none }


    html.setAttributes(attributes, range: NSRange(0..<html.length))

    return html
  }
}

我这样称呼它:

let attributes = [
  NSForegroundColorAttributeName: UIColor.lightGray,
  NSFontAttributeName : UIFont.systemFont(ofSize: 12).traits(traits: .traitItalic)
]

label?.attributedText = partialHTMLString.htmlAttributedString(attributes: attributes)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接