HTML 到 NSAttributedString 和 NSAttributedString 到 HTML
HTML to NSAttributedString and NSAttributedString to HTML
我想将 html 字符串转换为 NSAttributedString 然后处理字符串(更改颜色、字体大小、字体系列、背景-、前景色。 ..) 然后将字符串从 NSAttributedString.
转换回纯 html
转换 不是问题,但每次我将 html 转换为 NSAS 并返回 fontsize越来越大...
游乐场示例:
// Playground - noun: a place where people can play
// NSAS: - NSAttributedString
import UIKit
class Wrapper {
//MARK: fields
let apiHtml = "<div style='font-size: 18px'><span style='font-family:'andale mono', times;'>Dies</span> <span style='font-family:'comic sans ms', sans-serif;'>ist</span> <strong><span style='font-family:'andale mono', sans-serif;';>eine</span></strong> <em>formatierte</em> <span style='text-decoration:underline;'>Karte</span> <span style='font-size:16px;'>die</span> <span style='background-color:#ffff00;'>es</span> zu Übernehmen gilt</div>"
var newGeneratedHtml = ""
var textView : UITextView!
//MARK: constructor
init() {
//init textview
textView = UITextView(frame: CGRectMake(0, 0, 500, 300))
//convert html into NSAS and set it to textview
if let attributedText = getAttributedTextFromApiHtmlString(apiHtml) {
textView.attributedText = attributedText
}
//get html text from textfields NSAS
if let htmlText = getHtmlTextFromTextView() {
newGeneratedHtml = htmlText
println(htmlText)
}
//set the converted html from textfields NSAS
if let attributedText = getAttributedTextFromApiHtmlString(newGeneratedHtml) {
textView.attributedText = attributedText
}
//get html text from textfields NSAS
if let htmlText = getHtmlTextFromTextView() {
newGeneratedHtml = htmlText
println(htmlText)
}
}
//MARK: methods
func getAttributedTextFromApiHtmlString(text : String) -> NSAttributedString? {
if let attributedText = NSAttributedString(data: text.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!, options: [NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType], documentAttributes: nil, error: nil) {
return attributedText
}
return nil
}
func getHtmlTextFromTextView() -> String? {
let attributedTextFromTextView = textView.attributedText
if let htmlData = attributedTextFromTextView.dataFromRange(NSMakeRange(0, attributedTextFromTextView.length), documentAttributes: [NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType], error: nil) {
if let htmlString = NSString(data: htmlData, encoding: NSUTF8StringEncoding) {
return htmlString
}
}
return nil
}
}
var w = Wrapper()
这是游乐场的结果。你可以看到第二个文本比第一个文本大,但我没有改变任何地方的字体大小。
这是错误还是我必须设置固定字体大小?
更新:
我接受@Lou Franco 的回答。我不知道为什么 NSAS 将 px
转换为 pt
并返回,但这是我的解决方法:
func getAttributedTextFromApiHtmlString(text : String) -> NSAttributedString? {
if let attributedText = NSAttributedString(data: text.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, options: [NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType], documentAttributes: nil, error: nil) {
var res : NSMutableAttributedString = attributedText.mutableCopy() as NSMutableAttributedString
res.beginEditing()
var found : Bool = false;
res.enumerateAttribute(NSFontAttributeName, inRange:NSMakeRange(0, res.length) ,options:NSAttributedStringEnumerationOptions.allZeros, usingBlock: {(value:AnyObject!, range:NSRange, stop:UnsafeMutablePointer<ObjCBool>) -> Void in
if ((value) != nil) {
let oldFont = value as UIFont;
let newFont = oldFont.fontWithSize(15)
res.removeAttribute(NSFontAttributeName, range:range)
res.addAttribute(NSFontAttributeName, value: newFont, range: range)
found = true
}
})
if !found {
// No font was found - do something else?
}
res.endEditing()
return res
}
return nil
}
这样做的唯一缺点是您 失去了 在您的 NSAS 中不同的文本高度....
如果有人有解决方案或更好的解决方法,请随时 post 您的回答。
可能是往返的舍入误差。尝试使用整数点大小(使用 pt
而不是 px
)
好的,看看你的控制台输出,它正在将你的 px
翻译成 pt
,所以也许你可以通过获取来自转换的 HTML 并改变 pt
回到 px
。
我通过对字符串中的每个喜欢大小应用 0.75 比率来解决这个问题。假设您的属性字符串中有多种字体,当您循环遍历所有字体时,只需应用比率,然后就可以了。这是我在 swift 3.0 中的代码:
yourAttrStr.beginEditing()
yourAttrStr.enumerateAttribute(NSFontAttributeName, in: NSMakeRange(0, yourAttrStr.length), options: .init(rawValue: 0)) {
(value, range, stop) in
if let font = value as? UIFont {
let resizedFont = font.withSize(font.pointSize * 0.75)
yourAttrStr.addAttribute(NSFontAttributeName, value: resizedFont, range: range)
}
}
yourAttrStr.endEditing()//yourAttrStr will be the same size as html string
这是我的应用程序中运行的一段代码
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 }
html.beginEditing()
html.enumerateAttribute(NSFontAttributeName, in: NSMakeRange(0, html.length), options: .init(rawValue: 0)) {
(value, range, stop) in
if let font = value as? UIFont {
let resizedFont = font.withSize(font.pointSize * 0.75)
html.addAttribute(NSFontAttributeName,
value: resizedFont,
range: range)
}
}
html.endEditing()
return html
}
}
使用方法:
let htmlStr: String = "<font size=\"6\">font a</font><font size=\"16\">Font b</font>"
let attriStr: NSAttributedString? = htmlStr.htmlAttributedString()
在 Swift 3 中采用@fangming 的解决方案,对我有用:
func newAttrSize(blockQuote: NSAttributedString) -> NSAttributedString
{
let yourAttrStr = NSMutableAttributedString(attributedString: blockQuote)
yourAttrStr.enumerateAttribute(.font, in: NSMakeRange(0, yourAttrStr.length), options: .init(rawValue: 0)) {
(value, range, stop) in
if let font = value as? UIFont {
let resizedFont = font.withSize(font.pointSize * 0.75)
yourAttrStr.addAttribute(.font, value: resizedFont, range: range)
}
}
return yourAttrStr
}
我想将 html 字符串转换为 NSAttributedString 然后处理字符串(更改颜色、字体大小、字体系列、背景-、前景色。 ..) 然后将字符串从 NSAttributedString.
转换回纯 html转换 不是问题,但每次我将 html 转换为 NSAS 并返回 fontsize越来越大...
游乐场示例:
// Playground - noun: a place where people can play
// NSAS: - NSAttributedString
import UIKit
class Wrapper {
//MARK: fields
let apiHtml = "<div style='font-size: 18px'><span style='font-family:'andale mono', times;'>Dies</span> <span style='font-family:'comic sans ms', sans-serif;'>ist</span> <strong><span style='font-family:'andale mono', sans-serif;';>eine</span></strong> <em>formatierte</em> <span style='text-decoration:underline;'>Karte</span> <span style='font-size:16px;'>die</span> <span style='background-color:#ffff00;'>es</span> zu Übernehmen gilt</div>"
var newGeneratedHtml = ""
var textView : UITextView!
//MARK: constructor
init() {
//init textview
textView = UITextView(frame: CGRectMake(0, 0, 500, 300))
//convert html into NSAS and set it to textview
if let attributedText = getAttributedTextFromApiHtmlString(apiHtml) {
textView.attributedText = attributedText
}
//get html text from textfields NSAS
if let htmlText = getHtmlTextFromTextView() {
newGeneratedHtml = htmlText
println(htmlText)
}
//set the converted html from textfields NSAS
if let attributedText = getAttributedTextFromApiHtmlString(newGeneratedHtml) {
textView.attributedText = attributedText
}
//get html text from textfields NSAS
if let htmlText = getHtmlTextFromTextView() {
newGeneratedHtml = htmlText
println(htmlText)
}
}
//MARK: methods
func getAttributedTextFromApiHtmlString(text : String) -> NSAttributedString? {
if let attributedText = NSAttributedString(data: text.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!, options: [NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType], documentAttributes: nil, error: nil) {
return attributedText
}
return nil
}
func getHtmlTextFromTextView() -> String? {
let attributedTextFromTextView = textView.attributedText
if let htmlData = attributedTextFromTextView.dataFromRange(NSMakeRange(0, attributedTextFromTextView.length), documentAttributes: [NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType], error: nil) {
if let htmlString = NSString(data: htmlData, encoding: NSUTF8StringEncoding) {
return htmlString
}
}
return nil
}
}
var w = Wrapper()
这是游乐场的结果。你可以看到第二个文本比第一个文本大,但我没有改变任何地方的字体大小。
这是错误还是我必须设置固定字体大小?
更新:
我接受@Lou Franco 的回答。我不知道为什么 NSAS 将 px
转换为 pt
并返回,但这是我的解决方法:
func getAttributedTextFromApiHtmlString(text : String) -> NSAttributedString? {
if let attributedText = NSAttributedString(data: text.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, options: [NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType], documentAttributes: nil, error: nil) {
var res : NSMutableAttributedString = attributedText.mutableCopy() as NSMutableAttributedString
res.beginEditing()
var found : Bool = false;
res.enumerateAttribute(NSFontAttributeName, inRange:NSMakeRange(0, res.length) ,options:NSAttributedStringEnumerationOptions.allZeros, usingBlock: {(value:AnyObject!, range:NSRange, stop:UnsafeMutablePointer<ObjCBool>) -> Void in
if ((value) != nil) {
let oldFont = value as UIFont;
let newFont = oldFont.fontWithSize(15)
res.removeAttribute(NSFontAttributeName, range:range)
res.addAttribute(NSFontAttributeName, value: newFont, range: range)
found = true
}
})
if !found {
// No font was found - do something else?
}
res.endEditing()
return res
}
return nil
}
这样做的唯一缺点是您 失去了 在您的 NSAS 中不同的文本高度....
如果有人有解决方案或更好的解决方法,请随时 post 您的回答。
可能是往返的舍入误差。尝试使用整数点大小(使用 pt
而不是 px
)
好的,看看你的控制台输出,它正在将你的 px
翻译成 pt
,所以也许你可以通过获取来自转换的 HTML 并改变 pt
回到 px
。
我通过对字符串中的每个喜欢大小应用 0.75 比率来解决这个问题。假设您的属性字符串中有多种字体,当您循环遍历所有字体时,只需应用比率,然后就可以了。这是我在 swift 3.0 中的代码:
yourAttrStr.beginEditing()
yourAttrStr.enumerateAttribute(NSFontAttributeName, in: NSMakeRange(0, yourAttrStr.length), options: .init(rawValue: 0)) {
(value, range, stop) in
if let font = value as? UIFont {
let resizedFont = font.withSize(font.pointSize * 0.75)
yourAttrStr.addAttribute(NSFontAttributeName, value: resizedFont, range: range)
}
}
yourAttrStr.endEditing()//yourAttrStr will be the same size as html string
这是我的应用程序中运行的一段代码
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 }
html.beginEditing()
html.enumerateAttribute(NSFontAttributeName, in: NSMakeRange(0, html.length), options: .init(rawValue: 0)) {
(value, range, stop) in
if let font = value as? UIFont {
let resizedFont = font.withSize(font.pointSize * 0.75)
html.addAttribute(NSFontAttributeName,
value: resizedFont,
range: range)
}
}
html.endEditing()
return html
}
}
使用方法:
let htmlStr: String = "<font size=\"6\">font a</font><font size=\"16\">Font b</font>"
let attriStr: NSAttributedString? = htmlStr.htmlAttributedString()
在 Swift 3 中采用@fangming 的解决方案,对我有用:
func newAttrSize(blockQuote: NSAttributedString) -> NSAttributedString
{
let yourAttrStr = NSMutableAttributedString(attributedString: blockQuote)
yourAttrStr.enumerateAttribute(.font, in: NSMakeRange(0, yourAttrStr.length), options: .init(rawValue: 0)) {
(value, range, stop) in
if let font = value as? UIFont {
let resizedFont = font.withSize(font.pointSize * 0.75)
yourAttrStr.addAttribute(.font, value: resizedFont, range: range)
}
}
return yourAttrStr
}