開篇
看了看更新日期好久沒寫簡書了,經常還有小伙伴在文章下面評論,看到自己寫的東西還是有點用的,鼓勵自己接著堅持下去吧,哈哈。今天主要就寫寫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:@"http://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:@"http://ul"];
for (TFHppleElement *HppleElement in array) {
if ([HppleElement.attributes[@"type"]isEqualToString:@"disc"]) { //找出 ul標簽下 節點屬性type 屬性值為 disc 的數組
NSArray *array2 = [HppleElement searchWithXPathQuery:@"http://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];