开篇
看了看更新日期好久没写简书了,经常还有小伙伴在文章下面评论,看到自己写的东西还是有点用的,鼓励自己接着坚持下去吧,哈哈。今天主要就写写iOS中怎么解析HTML标签,我们常用的后台返回数据一般是json格式的但是有些时候如果我们收到的是带HTMl标签的我们该怎么处理他呢,今天就来说一说吧。
正文
前两天获取后台数据的时候,得到这么一条返回信息
"恭喜您获得<font color='red'>8.1元</font>现金奖励 "
本来简简单单的把返回数据展示到label上的事情一下子变得有趣起来,后台说是为了以后产品改返回内容的时候容易处理,可以这理由很强势。
但是作为开发的我们怎么处理呢,首先我们看下安卓的处理方法,安卓对处理这个还是比较粗暴的人家有系统方法,如下:
那么iOS端怎么处理呢,我们可以用webview,也可以用Label的attributedString属性,也可以直接简单粗暴的分割字符串,然后去除HTML标签,然后处理,听听就让人惆怅,然而毕竟是一种方法,能解决问题的方法都是好方法,我们就放一下最粗暴方法的主要代码(其余方法在评论补充有,哈哈),去除HTML标签的方法如下:
//过滤后台返回字符串中的标签
- (NSString *)flattenHTML:(NSString *)html {
NSScanner *theScanner;
NSString *text = nil;
theScanner = [NSScanner scannerWithString:html];
while ([theScanner isAtEnd] == NO) {
// find start of tag
[theScanner scanUpToString:@"<" intoString:NULL] ;
// find end of tag
[theScanner scanUpToString:@">" intoString:&text] ;
// replace the found tag with a space
//(you can filter multi-spaces out later if you wish)
html = [html stringByReplacingOccurrencesOfString:
[NSString stringWithFormat:@"%@>", text]
withString:@""];
}
MidStrTitle = html;
return html;
}
这样我们就处理掉了HTML标签,那么问题来了,如果我们要处理的是很多的HTML标签呢,我们该怎么处理呢,这就是这篇文章的目的。
TFHpple库
如果我们想要得到是如下一个HTML源码中某一个标签的内容呢,部分源码如下,这里只是放了标签部分的内容
<title>关于APP的声明</title>
</head>
<body>
<h3>关于APP的声明</h3>
<p>只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试</p>
<p>只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试</p>
<h3>联系我们</h3>
<p>若您在使用该APP有遇到任何问题或有新想法,都可以联系我们. 如下是我们的联系方式:</p>
<ul>
<li>只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试</li>
<li>E-mail: xxxxxxxxxxxxxxxxxxxxxxxxxx</li>
<li>phone: xxxxxxxxxxxxxxxxxx</li>
</ul>
<h3>感谢</h3>
<p>首先,感谢广大用户对公司的支持和鼓励,谢谢你们对我们的一路支持.</p>
<p>只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试</p>
<h3>版权声明</h3>
<p>只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试只是测试</p>
</body>
</html>
这里如果我要针对性取某一个标签的内容就要用到我们今天介绍的库了。
环境的配置
导入静态库
然后把导入的静态库添加到文件的路径
然后导入TFHpple库就可以了。
使用方法1,简单的标签形式取值法
直接上代码
NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
NSString *filePath =[resourcePath stringByAppendingPathComponent:@"about.html"];
NSData *data =[[NSData alloc]initWithContentsOfFile:filePath];
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; //data转字符串 为了打印不是乱码
NSLog(@"------%@",result);
TFHpple *Hpple = [[TFHpple alloc]initWithHTMLData:data];
//测试1:获取简单的标题
NSArray *array =[Hpple searchWithXPathQuery:@"//title"]; //获取到为title的标题
for (TFHppleElement *HppleElement in array) {
NSLog(@"测试1的目的标签内容:-- %@",HppleElement.text);
}
我们首先获取到本地的about.html的文件,然后转化为data,加UTF8编码转换为我们可以看到的容如下图:
上部分为HTML文件的原标签,下部分为我们去到的标签为“title”的内容。
这样我们就得到了我们想要的。
使用方法2:有自己属性的标签内容取值
上面的那个HTML文件由于内容的局限性不方便我们举例,我们使用的HTML标签源码如下:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>hello</title>
</head>
<body>hello world
<span>
</span>
无序列表
<ul type="disc">
<li>苹果</li>
<li>水果</li>
<li>桃子</li>
</ul>
<ul type="circle">
<li>苹果2</li>
<li>水果2</li>
<li>桃子2</li>
</ul>
</body>
</html>
我们想去取到的是无序列表 节点属性为type 属性值为disc的标签内容,显然上面的方法已经不能满足我们的需要,老规矩先上代码:
//测试2:获取更加详细的内容
NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
NSString *filePath =[resourcePath stringByAppendingPathComponent:@"first.html"];
NSData *data =[[NSData alloc]initWithContentsOfFile:filePath];
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; //data转字符串 为了打印不是乱码
NSLog(@"------%@",result);
TFHpple *Hpple = [[TFHpple alloc]initWithHTMLData:data];
NSArray *array =[Hpple searchWithXPathQuery:@"//ul"];
for (TFHppleElement *HppleElement in array) {
if ([HppleElement.attributes[@"type"]isEqualToString:@"disc"]) { //找出 ul标签下 节点属性type 属性值为 disc 的数组
NSArray *array2 = [HppleElement searchWithXPathQuery:@"//li"];
for (TFHppleElement *HppleElement2 in array2) {
NSLog(@"测试2的目的标签内容:-- %@",HppleElement2.text);
}
}
}
使用方法重点在下面的这个if语句的判断里
if ([HppleElement.attributes[@"type"]isEqualToString:@"disc"]) {
}
如果存在这种条件下的内容,根据这个BOOL值,去取到下面标签为“li‘的内容
运行结果如下:
项目中遇到的一些坑
我们取完了标签并不能结束,好不容易有时间就再写一下一些遇到的小的问题吧。
自定义键盘
自定义键盘也算是老问题了,由于情况的不同,我们可能需要定义一个完全自定义的键盘,来适应各种奇葩的需求。最近看代码的时候才发现不同的人写法真不一样,这里介绍一个个人认为比较简单的方法吧。
UITextField的inputView的属性,用法举例如下:
kkeyboardView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320 ,260 )] ;
kkeyboardView.backgroundColor = [UIColor lightGrayColor];
[self setUpMyKeyBoard2];
self.textfiled.inputView = kkeyboardView;
创建一个View 然后把它作为UITextField的inputView,这个时候就可以完全的自定义自己想要的自定义键盘了,产品你过来说说你还要键盘上有啥。
UIScrollView的滚动问题
前天同事说了一个奇怪的问题,说懒加载也写了,布局也搞了,偏移量也设置了,在别的页面都搞好了,这个页面的滚动试图忽然就不动了。老司机也翻车了喜闻乐见,但是问题怎么处理呢。
-(void)viewDidLayoutSubviews
{
_BaseScore.contentSize = CGSizeMake(SCREEN_WIDTH, 568.0 - 44);
}
一阵折腾之后给了他这个方法,把偏移量写在这个方法里就可以滚动了,同事不禁说老了老了,发现自己记忆越来越差了,哈哈,有一群这样的同事真的工作比较开心。
后记
今天的主要介绍就这么多吧,希望对需要的小伙伴有所帮助,有时间的话下次写一下,项目中用到的,商家端生成二维码收款,用户端扫描二维码付款,以及定时刷新,状态判断,扫描二维码生成邀请码等一系列二维码相关的功能。有写的不对地方的欢迎指出,大神轻喷,哈哈。
补充:
再补充两条简单情况下的方法:
- Label的attributedString属性
NSAttributedString * attrStr = [[NSAttributedString alloc] initWithData:[h5str dataUsingEncoding:NSUnicodeStringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];
[selflab setAttributedText:attrStr];
- 利用web view
_webView = [[UIWebView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
NSString *html_str = [NSString stringWithFormat:@"<div style='color:red'>666666</div> 测试 %@",@"新风作浪",@"2020-01-00"];
[self.webView loadHTMLString:html_str baseURL:nil];
[self.view addSubview:self.webView];