parsingHTML到NSAttributedText – 如何设置字体?
我正在尝试获取格式为html的文本片段,以在UITableViewCell中的iPhone上很好地显示。
到目前为止,我有这样的:
NSError* error; NSString* source = @"<strong>Nice</strong> try, Phil"; NSMutableAttributedString* str = [[NSMutableAttributedString alloc] initWithData:[source dataUsingEncoding:NSUTF8StringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]} documentAttributes:nil error:&error];
这种作品。 我收到了一些有“很好”的文字! 但是…它也将字体设置为Times Roman! 这不是我想要的字体。 我想我需要在documentAttributes中设置一些东西,但是,我无法在任何地方find任何示例。
#import "UILabel+HTML.h" @implementation UILabel (HTML) - (void)jaq_setHTMLFromString:(NSString *)string { string = [string stringByAppendingString:[NSString stringWithFormat:@"<style>body{font-family: '%@'; font-size:%fpx;}</style>", self.font.fontName, self.font.pointSize]]; self.attributedText = [[NSAttributedString alloc] initWithData:[string dataUsingEncoding:NSUnicodeStringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)} documentAttributes:nil error:nil]; } @end
这样你不需要指定你想要的字体,它将采用标签的字体和大小。
Swift版,基于Javier Querol给出的答案
extension UILabel { func setHTMLFromString(text: String) { let modifiedFont = NSString(format:"<span style=\"font-family: \(self.font!.fontName); font-size: \(self.font!.pointSize)\">%@</span>", text) as String let attrStr = try! NSAttributedString( data: modifiedFont.dataUsingEncoding(NSUnicodeStringEncoding, allowLossyConversion: true)!, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: NSUTF8StringEncoding], documentAttributes: nil) self.attributedText = attrStr } }
Swift 3.0和iOS 9+
extension UILabel { func setHTMLFromString(htmlText: String) { let modifiedFont = String(format:"<span style=\"font-family: '-apple-system', 'HelveticaNeue'; font-size: \(self.font!.pointSize)\">%@</span>", htmlText) //process collection values let attrStr = try! NSAttributedString( data: modifiedFont.data(using: .unicode, allowLossyConversion: true)!, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue], documentAttributes: nil) self.attributedText = attrStr } }
弄清楚了。 熊的位,也许不是最好的答案。
这段代码将会经历所有的字体变化。 我知道它是使用“Times New Roman”和“Times New Roman BoldMT”作为字体。 但是无论如何,这将find大胆的字体,让我重置它们。 我也可以重置尺寸。
我真的希望/想一想在parsing的时候可以设置这个方法,但是如果有的话我找不到它。
NSRange range = (NSRange){0,[str length]}; [str enumerateAttribute:NSFontAttributeName inRange:range options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired usingBlock:^(id value, NSRange range, BOOL *stop) { UIFont* currentFont = value; UIFont *replacementFont = nil; if ([currentFont.fontName rangeOfString:@"bold" options:NSCaseInsensitiveSearch].location != NSNotFound) { replacementFont = [UIFont fontWithName:@"HelveticaNeue-CondensedBold" size:25.0f]; } else { replacementFont = [UIFont fontWithName:@"HelveticaNeue-Thin" size:25.0f]; } [str addAttribute:NSFontAttributeName value:replacementFont range:range]; }];
我实际上find了一个解决这个问题的办法:
在parsing之前更改HTML响应string中的字体。
NSString *aux = [NSString stringWithFormat:@"<span style=\"font-family: YOUR_FONT_NAME; font-size: SIZE\">%@</span>", htmlResponse];
例:
NSString *aux = [NSString stringWithFormat:@"<span style=\"font-family: HelveticaNeue-Thin; font-size: 17\">%@</span>", [response objectForKey:@"content"]];
Swift版本:
let aux = "<span style=\"font-family: YOUR_FONT_NAME; font-size: SIZE\">\(htmlResponse)</span>"
更通用的方法是在枚举时查看字体特征,并创build具有相同特征(粗体,斜体等)的字体:
extension NSMutableAttributedString { /// Replaces the base font (typically Times) with the given font, while preserving traits like bold and italic func setBaseFont(baseFont: UIFont, preserveFontSizes: Bool = false) { let baseDescriptor = baseFont.fontDescriptor() beginEditing() enumerateAttribute(NSFontAttributeName, inRange: NSMakeRange(0, length), options: []) { object, range, stop in if let font = object as? UIFont { // Instantiate a font with our base font's family, but with the current range's traits let traits = font.fontDescriptor().symbolicTraits let descriptor = baseDescriptor.fontDescriptorWithSymbolicTraits(traits) let newFont = UIFont(descriptor: descriptor, size: preserveFontSizes ? descriptor.pointSize : baseDescriptor.pointSize) self.removeAttribute(NSFontAttributeName, range: range) self.addAttribute(NSFontAttributeName, value: newFont, range: range) } } endEditing() } }
是的,有一个更简单的解决scheme。 在html源代码中设置字体!
NSError* error; NSString* source = @"<strong>Nice</strong> try, Phil"; source = [source stringByAppendingString:@"<style>strong{font-family: 'Avenir-Roman';font-size: 14px;}</style>"]; NSMutableAttributedString* str = [[NSMutableAttributedString alloc] initWithData:[source dataUsingEncoding:NSUTF8StringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]} documentAttributes:nil error:&error];
希望这可以帮助。
如果在创buildNSAttributedString
的同时进行转换,上面的答案都可以正常工作。 但是我认为一个更好的解决scheme,对string本身起作用,因此不需要访问input,就是以下类别:
extension NSMutableAttributedString { func convertFontTo(font: UIFont) { var range = NSMakeRange(0, 0) while (NSMaxRange(range) < length) { let attributes = attributesAtIndex(NSMaxRange(range), effectiveRange: &range) if let oldFont = attributes[NSFontAttributeName] { let newFont = UIFont(descriptor: font.fontDescriptor().fontDescriptorWithSymbolicTraits(oldFont.fontDescriptor().symbolicTraits), size: font.pointSize) addAttribute(NSFontAttributeName, value: newFont, range: range) } } } }
用于:
let desc = NSMutableAttributedString(attributedString: *someNSAttributedString*) desc.convertFontTo(UIFont.systemFontOfSize(16))
适用于iOS 7+
使用NSHTMLTextDocumentType很慢,很难控制样式。 我build议你去尝试一下我的图书馆,叫做Atributika。 它有自己的快速parsing器。 你也可以有任何标签名称并为其定义任何样式。
例:
let str = "<strong>Nice</strong> try, Phil".style(tags: Style("strong").font(.boldSystemFont(ofSize: 15))).attributedString label.attributedText = str
你可以在这里findhttps://github.com/psharanda/Atributika
维克多解决scheme的改进,包括颜色:
extension UILabel { func setHTMLFromString(text: String) { let modifiedFont = NSString(format:"<span style=\"color:\(self.textColor.toHexString());font-family: \(self.font!.fontName); font-size: \(self.font!.pointSize)\">%@</span>", text) as String let attrStr = try! NSAttributedString( data: modifiedFont.dataUsingEncoding(NSUnicodeStringEncoding, allowLossyConversion: true)!, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: NSUTF8StringEncoding], documentAttributes: nil) self.attributedText = attrStr } }
为了这个工作,你还需要将ULColor的YLColor.swift转换为hex的转换https://gist.github.com/yannickl/16f0ed38f0698d9a8ae7
Swift 4+更新UILabel扩展
extension UILabel { func setHTMLFromString(text: String) { let modifiedFont = NSString(format:"<span style=\"font-family: \(self.font!.fontName); font-size: \(self.font!.pointSize)\">%@</span>" as NSString, text) let attrStr = try! NSAttributedString( data: modifiedFont.data(using: String.Encoding.unicode.rawValue, allowLossyConversion: true)!, options: [NSAttributedString.DocumentReadingOptionKey.documentType:NSAttributedString.DocumentType.html, NSAttributedString.DocumentReadingOptionKey.characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil) self.attributedText = attrStr } }
iOS 9+
extension UILabel { func setHTMLFromString(htmlText: String) { let modifiedFont = NSString(format:"<span style=\"font-family: '-apple-system', 'HelveticaNeue'; font-size: \(self.font!.pointSize)\">%@</span>" as NSString, htmlText) as String //process collection values let attrStr = try! NSAttributedString( data: modifiedFont.data(using: .unicode, allowLossyConversion: true)!, options: [NSAttributedString.DocumentReadingOptionKey.documentType:NSAttributedString.DocumentType.html, NSAttributedString.DocumentReadingOptionKey.characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil) self.attributedText = attrStr } }
感谢您的答案,我真的很喜欢扩展,但我还没有转换到迅速呢。 对那些还在Objective-C中的老生来说,这应该会有所帮助:D
-(void) setBaseFont:(UIFont*)font preserveSize:(BOOL) bPreserve { UIFontDescriptor *baseDescriptor = font.fontDescriptor; [self enumerateAttribute:NSFontAttributeName inRange:NSMakeRange(0, [self length]) options:0 usingBlock:^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) { UIFont *font = (UIFont*)value; UIFontDescriptorSymbolicTraits traits = font.fontDescriptor.symbolicTraits; UIFontDescriptor *descriptor = [baseDescriptor fontDescriptorWithSymbolicTraits:traits]; UIFont *newFont = [UIFont fontWithDescriptor:descriptor size:bPreserve?baseDescriptor.pointSize:descriptor.pointSize]; [self removeAttribute:NSFontAttributeName range:range]; [self addAttribute:NSFontAttributeName value:newFont range:range]; }]; }
快乐编码! –Greg框架
Swift 3string扩展,包括一个零字体。 没有字体的属性取自其他SO问题,不记得哪一个:(
extension String { var html2AttributedString: NSAttributedString? { guard let data = data(using: .utf8) else { return nil } do { return try NSAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue], documentAttributes: nil) } catch { print(error.localizedDescription) return nil } } public func getHtml2AttributedString(font: UIFont?) -> NSAttributedString? { guard let font = font else { return html2AttributedString } let modifiedString = "<style>body{font-family: '\(font.fontName)'; font-size:\(font.pointSize)px;}</style>\(self)"; guard let data = modifiedString.data(using: .utf8) else { return nil } do { return try NSAttributedString(data: data, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue], documentAttributes: nil) } catch { print(error) return nil } } }
其实,一个更简单,更清洁的方式存在。 parsingHTML之后,只需设置字体:
NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUTF8StringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)} documentAttributes:nil error:nil]; [text addAttributes:@{NSFontAttributeName: [UIFont fontWithName:@"Lato-Regular" size:20]} range:NSMakeRange(0, text.length)];