HTML 富文本的解析

The harsh truth is, I love this harsh, it never cheat.


一. 用 UILabel 加载富文本


1.将 HTML 字符串转化为标准 HTML 字符串

//将html语言符号转成oc里同样作用的符号
NSString *string = [string stringByReplacingOccurrencesOfString:@""" withString:@"\""];
string = [string stringByReplacingOccurrencesOfString:@"'" withString:@"'"];
string = [string stringByReplacingOccurrencesOfString:@"&lt;" withString:@"<"];
string = [string stringByReplacingOccurrencesOfString:@"&gt;" withString:@">"];
string = [string stringByReplacingOccurrencesOfString:@"&amp;" withString:@"&"];

2.将HTML字符串转换为attributeString

NSDictionary *options = @{ NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute :@(NSUTF8StringEncoding) };

NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];

NSAttributedString *normalAttr = [[NSAttributedString alloc] initWithData:data options:options documentAttributes:nil error:nil];

3.将其放入label中显示

self.label.attributedText = normalAttr;

注意

有时候后台返回的富文本可能是没有任何内容,只是一些代表空格的html符号,比如@"&lt;p&gt;&lt;br&gt;&lt;/p&gt"

这个时候可以去掉这些符号标签:

NSScanner * scanner = [NSScanner scannerWithString:string];
NSString * text = nil;
while([scanner isAtEnd]==NO)
{
//找到标签的起始位置
[scanner scanUpToString:@"<" intoString:nil];
//找到标签的结束位置
[scanner scanUpToString:@">" intoString:&text];
//替换字符
html = [html stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%@>",text] withString:@""];
}

封装方法,实际调用的时候可以这样

NSString *str = [self htmlEntityDecode:model.directions];
NSAttributedString * attributeStr = [self attributedStringWithHTMLString:str];
//可以在这里做个判断,如果 attributeStr 内容为空 ,则显示提示内容
if ([attributeStr isEqualToAttributedString:[[NSAttributedString alloc]initWithString:@""]]) {
    //...为空
}else
self.detailLabel.attributedText = attributeStr;

//将 &lt 等类似的字符转化为HTML中的“<”等
- (NSString *)htmlEntityDecode:(NSString *)string
{
string = [string stringByReplacingOccurrencesOfString:@"&quot;" withString:@"\""];
string = [string stringByReplacingOccurrencesOfString:@"&apos;" withString:@"'"];
string = [string stringByReplacingOccurrencesOfString:@"&lt;" withString:@"<"];
string = [string stringByReplacingOccurrencesOfString:@"&gt;" withString:@">"];
string = [string stringByReplacingOccurrencesOfString:@"&amp;" withString:@"&"]; // Do this last so that, e.g. @"&amp;lt;" goes to @"&lt;" not @"<"

return string;
}

//将HTML字符串转化为NSAttributedString富文本字符串
- (NSAttributedString *)attributedStringWithHTMLString:(NSString *)htmlString
{
/**处理数据为空*/
NSString *isEmptyStr = [self filterHTML:htmlString];
NSDictionary *isEmptyoptions = @{ NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute :@(NSUTF8StringEncoding) };

NSData *isEmptydata = [isEmptyStr dataUsingEncoding:NSUTF8StringEncoding];
//如果为空则返回这个
NSAttributedString *isEmpty = [[NSAttributedString alloc] initWithData:isEmptydata options:isEmptyoptions documentAttributes:nil error:nil];

/** 处理数据不为空 */
NSDictionary *options = @{ NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute :@(NSUTF8StringEncoding) };

NSData *data = [htmlString dataUsingEncoding:NSUTF8StringEncoding];
NSAttributedString *normalAttr = [[NSAttributedString alloc] initWithData:data options:options documentAttributes:nil error:nil];

if ([isEmpty isEqualToAttributedString:[[NSAttributedString alloc]initWithString:@""]]) {
return isEmpty;
}else{
return normalAttr;
}


}

//去掉 HTML 字符串中的标签
- (NSString *)filterHTML:(NSString *)html
{
NSScanner * scanner = [NSScanner scannerWithString:html];
NSString * text = nil;
while([scanner isAtEnd]==NO)
{
//找到标签的起始位置
[scanner scanUpToString:@"<" intoString:nil];
//找到标签的结束位置
[scanner scanUpToString:@">" intoString:&text];
//替换字符
html = [html stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%@>",text] withString:@""];
}
//    NSString * regEx = @"<([^>]*)>";
//    html = [html stringByReplacingOccurrencesOfString:regEx withString:@""];
return html;
}

二. 用 WKWebView 加载富文本


label加载会占用大量的内存,容易导致失帧情况,用 WKWebView 就不会出现这样的问题。

### 1.添加自适应宽度

 WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
 WKUserContentController *wkUController = [[WKUserContentController alloc] init];
 [wkUController addUserScript:wkUScript];
 
 WKWebViewConfiguration *wkWebConfig = [[WKWebViewConfiguration alloc] init];
 wkWebConfig.userContentController = wkUController;

### 2.创建 WKWebView

 //不能用自适应布局,如果不清楚内容大小,献给 1 个高度的大小
 WKWebView *wkWebView = [[WKWebView alloc]initWithFrame:CGRectMake(30,33, SCREEN_WIDTH, 1) configuration:wkWebConfig];
 //自身代理
 WKWebView *wkWebView.navigationDelegate = self;
 //禁止弹性
 WKWebView *wkWebView.scrollView.scrollEnabled = NO;
 设置滑动代理
 WKWebView *wkWebView.scrollView.delegate = self;

### 3.加载富文本

 NSString *str = [self htmlEntityDecode:url];

 [wkWebView loadHTMLString:str baseURL:nil];