Ios Swift-更改具有自己样式的HTML字符串的字体
我从WordPressAPI中获取一个HTML字符串,并将其解析为一个属性字符串,以在我的应用程序中显示它。由于字符串有自己的样式,它显示不同的字体和大小,这影响了我们的设计选择 我要做的是更改整个属性字符串的字体及其大小 我尝试在属性字符串的选项中执行此操作,但它没有执行任何操作:Ios Swift-更改具有自己样式的HTML字符串的字体,ios,swift,nsattributedstring,Ios,Swift,Nsattributedstring,我从WordPressAPI中获取一个HTML字符串,并将其解析为一个属性字符串,以在我的应用程序中显示它。由于字符串有自己的样式,它显示不同的字体和大小,这影响了我们的设计选择 我要做的是更改整个属性字符串的字体及其大小 我尝试在属性字符串的选项中执行此操作,但它没有执行任何操作: let attributedT = try! NSAttributedString( data: nContent!.decodeHTML().data(using: String.Enco
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
有人对如何实现这一目标有什么想法吗
另外,我知道我可以在字符串的开头或结尾添加CSS标记,但这会覆盖其中的其他样式吗?另外,如果这是一个有效的解决方案,您能提供一个如何执行的示例吗?基本上,您要做的是将NSAttributedString转换为NSMutableAttributedString
let attributedT = // ... attributed string
let mutableT = NSMutableAttributedString(attributedString:attributedT)
现在,您可以调用将属性(例如不同的字体)应用于任何所需的范围,例如整个范围
然而,不幸的是,没有符号特征(如斜体)的字体与具有符号特征的字体是不同的字体。因此,您需要一个实用程序,从一种字体复制现有的符号特征,并将其应用于另一种字体:
func applyTraitsFromFont(_ f1: UIFont, to f2: UIFont) -> UIFont? {
let t = f1.fontDescriptor.symbolicTraits
if let fd = f2.fontDescriptor.withSymbolicTraits(t) {
return UIFont.init(descriptor: fd, size: 0)
}
return nil
}
好的,那么,用这个工具,让我们试试。我将从一些简单的HTML开始,并将其转换为属性字符串,正如您所做的:
let html = "<p>Hello <i>world</i>, hello</p>"
let data = html.data(using: .utf8)!
let att = try! NSAttributedString.init(
data: data, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil)
let matt = NSMutableAttributedString(attributedString:att)
结果如下:
显然,根据您的设计需要,您可以将此过程调整得更加复杂。setAttributes将重置HTML中的所有属性。我编写了一个扩展方法来避免这种情况: Swift 4
public convenience init?(HTMLString html: String, font: UIFont? = nil) throws {
let options : [NSAttributedString.DocumentReadingOptionKey : Any] =
[NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html,
NSAttributedString.DocumentReadingOptionKey.characterEncoding: String.Encoding.utf8.rawValue]
guard let data = html.data(using: .utf8, allowLossyConversion: true) else {
throw NSError(domain: "Parse Error", code: 0, userInfo: nil)
}
if let font = font {
guard let attr = try? NSMutableAttributedString(data: data, options: options, documentAttributes: nil) else {
throw NSError(domain: "Parse Error", code: 0, userInfo: nil)
}
var attrs = attr.attributes(at: 0, effectiveRange: nil)
attrs[NSAttributedStringKey.font] = font
attr.setAttributes(attrs, range: NSRange(location: 0, length: attr.length))
self.init(attributedString: attr)
} else {
try? self.init(data: data, options: options, documentAttributes: nil)
}
}
测试样本:
let html = "<html><body><h1 style=\"color:red;\">html text here</h1></body></html>"
let font = UIFont.systemFont(ofSize: 16)
var attr = try NSMutableAttributedString(HTMLString: html, font: nil)
var attrs = attr?.attributes(at: 0, effectiveRange: nil)
attrs?[NSAttributedStringKey.font] as? UIFont
// print: <UICTFont: 0x7ff19fd0a530> font-family: "TimesNewRomanPS-BoldMT"; font-weight: bold; font-style: normal; font-size: 24.00pt
attr = try NSMutableAttributedString(HTMLString: html, font: font)
attrs = attr?.attributes(at: 0, effectiveRange: nil)
attrs?[NSAttributedStringKey.font] as? UIFont
// print: <UICTFont: 0x7f8c0cc04620> font-family: ".SFUIText"; font-weight: normal; font-style: normal; font-size: 16.00pt
let html=“此处为html文本”
让font=UIFont.systemFont(of大小:16)
var attr=try nsmutableAttributeString(HTMLString:html,font:nil)
var attrs=attr?.attributes(at:0,effectiveRange:nil)
属性?[NSAttributedStringKey.font]作为?UIFont
//打印:字体系列:“TimesNewRomanPS BoldMT”;字体大小:粗体;字体风格:普通;字体大小:24.00pt
attr=try nsmutableAttributeString(HTMLString:html,font:font)
attrs=attr?.attributes(at:0,effectiveRange:nil)
属性?[NSAttributedStringKey.font]作为?UIFont
//打印:字体系列:“.SFUIText”;字体大小:正常;字体风格:普通;字体大小:16.00pt
Swift 4解决方案
带有方便初始值设定项的扩展名NSAttributedString
- 枚举属性字符串(HTML文档)字体属性,并替换为提供的
UIFont
- 保留原始HTML字体大小,或使用提供的
,@请参阅UIFont
参数中的字体大小useDocumentFontSize
- 此方法可以简单地将HTML转换为NSAttributedString,而无需对字体进行超负荷操作,只需跳过字体参数,@see
语句guard
用法-1(替换字体) 用法-3(仅将HTML转换为NSAttribute字符串)
让attr=try?NSAttributedString(htmlString:你好世界!”)
Swift 3我以前(Swift 4)解决方案的版本
let font=“%@”
让html=String(格式:font,yourhtmlstring)
loadHTMLString(html,baseURL:nil)
只想感谢@AamirR的回复,并警告其他未来用户代码中的一个小错误
如果您使用它,您可能会遇到粗体和斜体字符串的问题,因为最后只使用了其中一个特征。这与修复的bug代码相同,希望有帮助:
extension NSAttributedString {
convenience init(htmlString html: String, font: UIFont? = nil, useDocumentFontSize: Bool = true) throws {
let options: [String : Any] = [
NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute: 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(NSFontAttributeName, in: range, options: .longestEffectiveRangeNotRequired) { attrib, range, _ in
if let htmlFont = attrib as? UIFont {
var traits = htmlFont.fontDescriptor.symbolicTraits
var descrip = htmlFont.fontDescriptor.withFamily(fontFamily)
if (traits.rawValue & UIFontDescriptorSymbolicTraits.traitBold.rawValue) != 0 {
traits = traits.union(.traitBold)
}
if (traits.rawValue & UIFontDescriptorSymbolicTraits.traitItalic.rawValue) != 0 {
traits = traits.union(.traitItalic)
}
descrip = descrip.withSymbolicTraits(traits)!
attr.addAttribute(NSFontAttributeName, value: UIFont(descriptor: descrip, size: fontSize ?? htmlFont.pointSize), range: range)
}
}
self.init(attributedString: attr)
}
}
setAttributes将重置HTML中的所有属性。对,我的意思是
addAttributes
。现在修好了。谢谢你捕捉到这个。我正在使用这个方法。我面临一个问题。每当我将应用程序中添加的自定义字体传递给此:让f2=UIFont(名称:“Georgia”,大小:20)。字体样式不起作用,但大小起作用。它适用于xcode中的其他字体系列。@SNarula若有问题,请提问。此解决方案非常有效。但我很惊讶,一个简单的任务需要这么长的代码。请将扩展名中的“text”改为“html”。这将使答案完整且正确。@bubuxu,我看到了与您在这里提到的相同的日志(正确的字体系列、字体类型等),但当我将attr设置为UILabel时,它不起作用。提示(未指出,但当前答案):NSAttributeString的文档(数据:选项:documentAttributes:)声明您不能将NSFontAttributeName
放入选项中,它不会被读取。这就是为什么你的代码没有达到你期望的效果。我发现,“DocumentReadingOptionKey”在Swift中不可用。从那以后他们有没有用别的东西来代替它?谷歌搜索没有发现任何结果。@keverly正如前面提到的Swift 4解决方案(见第一行),如果您使用的是Swift 3.x,请检查我的新答案是否有Swift 3等效答案感谢您的回复。我之所以这么问,是因为我去了“项目”->“构建设置”->“Swift语言版本”,上面写着4。不过肯定是另一个问题。谢谢你快速准确的回答。。我一直在搜索这个。你只需添加一些注释,解释为什么你不使用它来更改webview的字体,你可以在你的webview html字符串中添加任何自定义字体。
let font = UIFont(name: fontName, size: fontSize)
textAttributes[NSFontAttributeName] = font
self.attributedText = NSAttributedString(string: self.text, attributes: textAttributes)
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)
}
}
let attr = try? NSAttributedString(htmlString: "<strong>Hello</strong> World!", font: UIFont.systemFont(ofSize: 34, weight: .thin))
let attr = try! NSMutableAttributedString(htmlString: "<strong>Hello</strong> World!", font: UIFont.systemFont(ofSize: 34, weight: .thin))
attr.append(NSAttributedString(string: " MINIMIZE", attributes: [.link: "@m"]))
let attr = try? NSAttributedString(htmlString: "<strong>Hello</strong> World!")
extension NSAttributedString {
convenience init(htmlString html: String, font: UIFont? = nil, useDocumentFontSize: Bool = true) throws {
let options: [String : Any] = [
NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute: 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(NSFontAttributeName, 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(NSFontAttributeName, value: UIFont(descriptor: descrip, size: fontSize ?? htmlFont.pointSize), range: range)
}
}
self.init(attributedString: attr)
}
}
let font = "<font face='Montserrat-Regular' size='13' color= 'black'>%@"
let html = String(format: font, yourhtmlstring)
webView.loadHTMLString(html, baseURL: nil)
extension NSAttributedString {
convenience init(htmlString html: String, font: UIFont? = nil, useDocumentFontSize: Bool = true) throws {
let options: [String : Any] = [
NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute: 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(NSFontAttributeName, in: range, options: .longestEffectiveRangeNotRequired) { attrib, range, _ in
if let htmlFont = attrib as? UIFont {
var traits = htmlFont.fontDescriptor.symbolicTraits
var descrip = htmlFont.fontDescriptor.withFamily(fontFamily)
if (traits.rawValue & UIFontDescriptorSymbolicTraits.traitBold.rawValue) != 0 {
traits = traits.union(.traitBold)
}
if (traits.rawValue & UIFontDescriptorSymbolicTraits.traitItalic.rawValue) != 0 {
traits = traits.union(.traitItalic)
}
descrip = descrip.withSymbolicTraits(traits)!
attr.addAttribute(NSFontAttributeName, value: UIFont(descriptor: descrip, size: fontSize ?? htmlFont.pointSize), range: range)
}
}
self.init(attributedString: attr)
}
}