ext将html代码转为字符串,在iOS中将HTML转换为NSAttributedString

在iOS 7中,UIKit添加了一个initWithData:options:documentAttributes:error:方法,它可以使用HTML初始化NSAtttributedString,例如:

[[NSAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUTF8StringEncoding]

options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,

NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)}

documentAttributes:nil error:nil];

在Swift中:

let htmlData = NSString(string: details).data(using: String.Encoding.unicode.rawValue)

let options = [NSAttributedString.DocumentReadingOptionKey.documentType:

NSAttributedString.DocumentType.html]

let attributedString = try? NSMutableAttributedString(data: htmlData ?? Data(),

options: options,

documentAttributes: nil)

Github的Oliver Drobnik正在对NSAttributedString进行一项正在进行的开源添加。它使用NSScanner进行HTML解析。

从HTML创建NSAttributedString必须在主线程上完成!

更新:事实证明,NSAttributedString HTML呈现依赖于WebKit,必须在主线程上运行,否则偶尔会使用SIGTRAP使应用程序崩溃。

新Relic崩溃日志:

下面是一个更新的线程安全的Swift 2 String扩展:

extension String {

func attributedStringFromHTML(completionBlock:NSAttributedString? ->()) {

guard let data = dataUsingEncoding(NSUTF8StringEncoding) else {

print("Unable to decode data from html string: (self)")

return completionBlock(nil)

}

let options = [NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType,

NSCharacterEncodingDocumentAttribute: NSNumber(unsignedInteger:NSUTF8StringEncoding)]

dispatch_async(dispatch_get_main_queue()) {

if let attributedString = try? NSAttributedString(data: data, options: options, documentAttributes: nil) {

completionBlock(attributedString)

} else {

print("Unable to create attributed string from html string: (self)")

completionBlock(nil)

}

}

}

}

用法:

let html = "

Here is some HTML
"

html.attributedStringFromHTML { attString in

self.bodyLabel.attributedText = attString

}

输出:

NSAttributedString上的Swift初始化程序扩展

我倾向于将此作为NSAttributedString的延伸,而不是String。我尝试将它作为静态扩展和初始化器。我更喜欢初始化器,这是我在下面包含的内容。

斯威夫特4

internal convenience init?(html: String) {

guard let data = html.data(using: String.Encoding.utf16, allowLossyConversion: false) else {

return nil

}

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

return nil

}

self.init(attributedString: attributedString)

}

斯威夫特3

extension NSAttributedString {

internal convenience init?(html: String) {

guard let data = html.data(using: String.Encoding.utf16, allowLossyConversion: false) else {

return nil

}

guard let attributedString = try? NSMutableAttributedString(data: data, options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil) else {

return nil

}

self.init(attributedString: attributedString)

}

}

let html = "Hello World!"

let attributedString = NSAttributedString(html: html)

这是一个用Swift编写的String扩展,用于将HTML字符串作为NSAttributedString返回。

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 = "Hello u{2022} babe".htmlAttributedString()

在上面,我特意添加了一个unicode u2022来显示它正确呈现unicode。

一个小问题:NSAttributedString使用的默认编码是NSUTF16StringEncoding(不是UTF8!)。

Swift 3.0 Xcode 8版

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

}

您现在唯一的解决方案是解析HTML,使用给定的point / font / etc属性构建一些节点,然后将它们组合成NSAttributedString。这是很多工作,但如果做得正确,将来可以重复使用。

对Andrew的解决方案进行了一些修改,并将代码更新为Swift 3:

此代码现在使用UITextView作为self并能够继承其原始字体,字体大小和文本颜色

注意:toHexString()是此处的延伸

extension UITextView {

func setAttributedStringFromHTML(_ htmlCode: String, completionBlock: @escaping (NSAttributedString?) ->()) {

let inputText = "(htmlCode)"

guard let data = inputText.data(using: String.Encoding.utf16) else {

print("Unable to decode data from html string: (self)")

return completionBlock(nil)

}

DispatchQueue.main.async {

if let attributedString = try? NSAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil) {

self.attributedText = attributedString

completionBlock(attributedString)

} else {

print("Unable to create attributed string from html string: (self)")

completionBlock(nil)

}

}

}

}

用法示例:

mainTextView.setAttributedStringFromHTML("Hello world!") { _ in }

斯威夫特4

NSAttributedString方便初始化程序

没有额外的警卫

抛出错误

extension NSAttributedString {

convenience init(htmlString html: String) throws {

try self.init(data: Data(html.utf8), options: [

.documentType: NSAttributedString.DocumentType.html,

.characterEncoding: String.Encoding.utf8.rawValue

], documentAttributes: nil)

}

}

用法

UILabel.attributedText = try? NSAttributedString(htmlString: "Hello World!")

以上解决方案是正确的。

[[NSAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUTF8StringEncoding]

options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,

NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)}

documentAttributes:nil error:nil];

但是如果你在ios 8.1,2或3上运行应用程序wioll会崩溃。

为了避免崩溃,您可以做的是:在队列中运行它。所以它总是在主线程上。

使用NSHTMLTextDocumentType很慢并且很难控制样式。我建议你试试我的图书馆,叫做Atributika。它有自己非常快速的HTML解析器。您还可以拥有任何标签名称并为其定义任何样式。

例:

let str = "Hello World!".style(tags:

Style("strong").font(.boldSystemFont(ofSize: 15))).attributedString

label.attributedText = str

你可以在这里找到它https://github.com/psharanda/Atributika

斯威夫特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

}

}

并使用:

let str = "

Hello bro

Come On

Go sis

  • ME 1
  • ME 2

It is me bro , remember please

"

self.contentLabel.attributedText = str.htmlAttributedString()

有用的扩展

受到这个主题,pod和Erica Sadun在iOS Gourmet Cookbook p.80中的ObjC示例的启发,我在plain12ѭ和NSAttributedString上写了一个扩展来在HTML普通字符串和NSAttributedStrings之间来回转换,反之亦然 - 在GitHub这里,我发现有帮助。

签名是(再次,Gist中的完整代码,上面的链接):

extension NSAttributedString {

func encodedString(ext: DocEXT) -> String?

static func fromEncodedString(_ eString: String, ext: DocEXT) -> NSAttributedString?

static func fromHTML(_ html: String) -> NSAttributedString? // same as above, where ext = .html

}

extension String {

func attributedString(ext: DocEXT) -> NSAttributedString?

}

enum DocEXT: String { case rtfd, rtf, htm, html, txt }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值