在移動應(yīng)用開發(fā)中,客戶端經(jīng)常要與服務(wù)器進(jìn)行交互,獲得服務(wù)器的數(shù)據(jù),進(jìn)行展示。那么獲取的數(shù)據(jù)的格式,就是JSon或者Xml格式(大多數(shù)),而現(xiàn)在,因?yàn)镴Son格式的輕量級,和方便使用的特性,在市場占有中已經(jīng)90%左右。
我們來看看JSon格式的數(shù)據(jù)長什么樣子:
```
{
"access_token": "ACCESS_TOKEN", "expires_in": 1234, "remind_in":"798114", "uid":"12341234"
}
```
這是一段新浪微博返回的JSon格式數(shù)據(jù),是不是覺得樣子長得很像OC中的字典,對,沒錯(cuò),在iOS開發(fā)中我們也是要將這種數(shù)據(jù)轉(zhuǎn)化成OC的數(shù)據(jù)類型,方便我們使用。
在上面的數(shù)據(jù)中,我們注意到:JSon數(shù)據(jù)的key都有“”包裹,這說明你觀察的挺仔細(xì)的。這也是JSon數(shù)據(jù)的格式要求,那么,JSon數(shù)據(jù)怎么轉(zhuǎn)換成OC的數(shù)據(jù)類型呢???我們先看看他們之間的聯(lián)系吧。
你要是還不清楚這張圖在說什么,就看看下面的對應(yīng)關(guān)系:
JSON數(shù)據(jù)(NSData) -> OC對象(Foundation Object)
這下肯定知道什么意思了吧。
有了這個(gè)一一對應(yīng)的關(guān)系,我們就能方便的進(jìn)行轉(zhuǎn)換了。
JSon解析方法
---
性能最好的解析方法是:蘋果原生(自帶):NSJSONSerialization
也有第三方框架:JSONKit、SBJson、TouchJSON(性能從左到右,越來越差)
但是我們并不會都學(xué),因?yàn)閷W(xué)那么多也不會都用得上,so...開始吧
我們來學(xué)習(xí)一下性能最好
的解析方式:NSJSONSerialization
常使用的方法是:
+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
參數(shù)options詳解:
- NSJSONReadingOptions - NSJSONReadingMutableContainers = (1UL << 0) - 創(chuàng)建出來的數(shù)組和字典就是可變 - NSJSONReadingMutableLeaves = (1UL << 1) - 數(shù)組或者字典里面的字符串是可變的 - NSJSONReadingAllowFragments - 允許解析出來的對象不是字典或者數(shù)組,比如直接是字符串或者NSNumber
這樣干講是不是覺得學(xué)的不牢固,那么我們來試試?yán)訉W(xué)習(xí)吧:
//請求服務(wù)器的數(shù)據(jù) NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { //查看原數(shù)據(jù)的類型 NSLog(@"原數(shù)據(jù)%@",data); //對數(shù)據(jù)用NSJSONSerialization解析成OC數(shù)據(jù)類型 NSMutableDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; NSLog(@"轉(zhuǎn)換后的數(shù)據(jù)%@",dict); }];
上面的例子你可以實(shí)現(xiàn)將服務(wù)器返回的數(shù)據(jù)轉(zhuǎn)換成OC的數(shù)據(jù)
函數(shù)原型
+ (NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;
參數(shù):NSJSONWritingPRettyPrinted 表示: 對轉(zhuǎn)換之后的JSON進(jìn)行排版
//創(chuàng)建字典 NSDictionary *dict = @{ @"name": @"xueyinliang", @"car":@"baoma", @"id":@1 }; NSLog(@"%@",dict); //將字典轉(zhuǎn)換成JSon數(shù)據(jù) NSData *data =[NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil]; NSLog(@"%@",data);
打印結(jié)果:
2015-08-11 15:32:46.890 JSonAndOC[4767:149687] { car = baoma; id = 1; name = xueyinliang;}2015-08-11 15:32:46.894 JSonAndOC[4767:149687] <7b0a2020 226e616d 6522203a 20227875 6579696e 6c69616e 67222c0a 20202263 61722220 3a202262 616f6d61 222c0a20 20226964 22203a20 310a7d>
這樣,我們就輕松學(xué)會了JSon和OC數(shù)據(jù)類型的轉(zhuǎn)換了。
雖然,JSon數(shù)據(jù)的市場應(yīng)用占有率很大,但是我們還是要學(xué)習(xí)一下XML數(shù)據(jù)的解析。因?yàn)檫@種格式的數(shù)據(jù)還是有一些公司會用到的。
xml數(shù)據(jù)是一種可擴(kuò)展的標(biāo)記語言,因?yàn)樗拿恳粋€(gè)元素都是由特定的標(biāo)記擴(kuò)起來的。
例如:
每一個(gè)元素都有一個(gè)開始和結(jié)束標(biāo)簽
<video>元素名</video>
元素可以嵌套子元素
<video> <name>世界你好</name> <length>30</length></video>
所有元素前面要有聲明
<?xml version="1.0" encoding="UTF-8" ?>
注意:這里的所有空格和換行,也是數(shù)據(jù)的一部分,會被處理。這也是為什么xml數(shù)據(jù)容量大的原因。
下面,我們來學(xué)習(xí)一下怎么解析xml數(shù)據(jù),這才是重點(diǎn)。
XML的解析方式有2種
下面將給出選擇方案
:(基于兩種方式的特點(diǎn)選擇)
XML解析方式的選擇建議
我們必須知道上面的這幾種方法各有什么特點(diǎn),才會使用:
蘋果原生
NSXMLParser:SAX方式解析,使用簡單
第三方框架
libxml2:純C語言,默認(rèn)包含在iOS SDK中,同時(shí)支持DOM和SAX方式解析GDataXML:DOM方式解析,由Google開發(fā),基于libxml2
雖然libxml2可以同時(shí)支持dom和sax方式的解析,但是因?yàn)槠涫褂寐闊栽趯?shí)際開發(fā)中,并不常用,而是SAX方式解析大文件的時(shí)候使用NSXMLParser,DOM方式解析小文件的時(shí)候使用GDataXML或NSXMLParser。
XML解析的方式介紹過了,我們再來看看到底怎么使用他們吧。
使用NSXMLParser解析數(shù)據(jù)很簡單,你只需要傳遞過來XML數(shù)據(jù),然后在NSXMLParser的代理方法里面解析就好了。這時(shí)候NSXMLParser的代理方法會當(dāng)讀到XML文件的開頭和結(jié)尾,以及讀到元素標(biāo)簽的開始和結(jié)尾的時(shí)候通知代理,并調(diào)用相應(yīng)的代理方法來執(zhí)行。為了防止有朋友不清楚哪里是XML文件的開頭和結(jié)尾,哪里是元素的開頭和結(jié)尾,這里給出一張圖來明確表示一下:
下面給出代碼如何開始和如何設(shè)置代理方法:
// 傳入XML數(shù)據(jù),創(chuàng)建解析器NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];// 設(shè)置代理,監(jiān)聽解析過程parser.delegate = self;// 開始解析[parser parse];
代理方法
當(dāng)掃描到文檔的開始時(shí)調(diào)用(開始解析)- (void)parserDidStartDocument:(NSXMLParser *)parser當(dāng)掃描到文檔的結(jié)束時(shí)調(diào)用(解析完畢)- (void)parserDidEndDocument:(NSXMLParser *)parser當(dāng)掃描到元素的開始時(shí)調(diào)用(attributeDict存放著元素的屬性)- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict當(dāng)掃描到元素的結(jié)束時(shí)調(diào)用- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName/** * 解析發(fā)生錯(cuò)誤時(shí)調(diào)用 */- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError;
在獲取到網(wǎng)絡(luò)數(shù)據(jù)以后:
// 1.創(chuàng)建XML解析器NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];// 2.成為NSXMLParser的代理parser.delegate = self;// 3.開始解析XML[parser parse];
然后在代理方法中拿到數(shù)據(jù):
/** * 開始解析XML文檔中的每一個(gè)元素時(shí)調(diào)用 */- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{ // 2.videos // 3.video // 5.video if ([elementName isEqualToString:@"videos"]) { return; } XMGVideo *video = [XMGVideo objectWithKeyValues:attributeDict];//使用MJExtension轉(zhuǎn)換模型 [self.videos addObject:video];}
然后就可以拿到數(shù)據(jù)數(shù)組,進(jìn)行各種顯示的操作了
1,GDataXML基于libxml2庫,得做以下配置
導(dǎo)入libxml2庫
設(shè)置libxml2的頭文件搜索路徑(為了能找到libxml2庫的所有頭文件)
在Head Search Path中加入/usr/include/libxml2
設(shè)置鏈接參數(shù)(自動鏈接libxml2庫)
在Other Linker Flags中加入-lxml2
由于GDataXML是非ARC的,因此得設(shè)置編譯參數(shù)
GDataXMLDocument:代表整個(gè)XML文檔
GDataXMLElement
代表文檔中的每個(gè)元素
使用attributeForName:方法可以獲得屬性值
在獲取到網(wǎng)絡(luò)數(shù)據(jù)以后:
// 1.加載所有的xml到內(nèi)存中 GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data options:kNilOptions error:nil]; // 2.獲取根元素 GDataXMLElement *rootElement = doc.rootElement; // 3.從根元素中獲取所有子元素 NSArray *elements = [rootElement elementsForName:@"video"]; // 4.將子元素中的屬性轉(zhuǎn)換為模型 for (GDataXMLElement *ele in elements) { XMGVideo *video = [[XMGVideo alloc] init]; video.image = [ele attributeForName:@"image"].stringValue; video.url = [ele attributeForName:@"url"].stringValue; video.name = [ele attributeForName:@"name"].stringValue; video.length = @([ele attributeForName:@"length"].stringValue.integerValue); [self.dataArray addObject:video]; //dataArray是數(shù)據(jù)的數(shù)組 }
然后就可以拿到數(shù)據(jù)數(shù)組,進(jìn)行各種顯示的操作了
如果還有哪里不懂的,
新聞熱點(diǎn)
疑難解答
圖片精選