在移動應用開發中,客戶端經常要與服務器進行交互,獲得服務器的數據,進行展示。那么獲取的數據的格式,就是JSon或者Xml格式(大多數),而現在,因為JSon格式的輕量級,和方便使用的特性,在市場占有中已經90%左右。
我們來看看JSon格式的數據長什么樣子:
```
{
"access_token": "ACCESS_TOKEN", "expires_in": 1234, "remind_in":"798114", "uid":"12341234"
}
```
這是一段新浪微博返回的JSon格式數據,是不是覺得樣子長得很像OC中的字典,對,沒錯,在iOS開發中我們也是要將這種數據轉化成OC的數據類型,方便我們使用。
在上面的數據中,我們注意到:JSon數據的key都有“”包裹,這說明你觀察的挺仔細的。這也是JSon數據的格式要求,那么,JSon數據怎么轉換成OC的數據類型呢???我們先看看他們之間的聯系吧。
你要是還不清楚這張圖在說什么,就看看下面的對應關系:
JSON數據(NSData) -> OC對象(Foundation Object)
這下肯定知道什么意思了吧。
有了這個一一對應的關系,我們就能方便的進行轉換了。
JSon解析方法
---
性能最好的解析方法是:蘋果原生(自帶):NSJSONSerialization
也有第三方框架:JSONKit、SBJson、TouchJSON(性能從左到右,越來越差)
但是我們并不會都學,因為學那么多也不會都用得上,so...開始吧
我們來學習一下性能最好
的解析方式:NSJSONSerialization
常使用的方法是:
+ (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
參數options詳解:
- NSJSONReadingOptions - NSJSONReadingMutableContainers = (1UL << 0) - 創建出來的數組和字典就是可變 - NSJSONReadingMutableLeaves = (1UL << 1) - 數組或者字典里面的字符串是可變的 - NSJSONReadingAllowFragments - 允許解析出來的對象不是字典或者數組,比如直接是字符串或者NSNumber
這樣干講是不是覺得學的不牢固,那么我們來試試例子學習吧:
//請求服務器的數據 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) { //查看原數據的類型 NSLog(@"原數據%@",data); //對數據用NSJSONSerialization解析成OC數據類型 NSMutableDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; NSLog(@"轉換后的數據%@",dict); }];
上面的例子你可以實現將服務器返回的數據轉換成OC的數據
函數原型
+ (NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;
參數:NSJSONWritingPRettyPrinted 表示: 對轉換之后的JSON進行排版
//創建字典 NSDictionary *dict = @{ @"name": @"xueyinliang", @"car":@"baoma", @"id":@1 }; NSLog(@"%@",dict); //將字典轉換成JSon數據 NSData *data =[NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil]; NSLog(@"%@",data);
打印結果:
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>
這樣,我們就輕松學會了JSon和OC數據類型的轉換了。
雖然,JSon數據的市場應用占有率很大,但是我們還是要學習一下XML數據的解析。因為這種格式的數據還是有一些公司會用到的。
xml數據是一種可擴展的標記語言,因為它的每一個元素都是由特定的標記擴起來的。
例如:
每一個元素都有一個開始和結束標簽
<video>元素名</video>
元素可以嵌套子元素
<video> <name>世界你好</name> <length>30</length></video>
所有元素前面要有聲明
<?xml version="1.0" encoding="UTF-8" ?>
注意:這里的所有空格和換行,也是數據的一部分,會被處理。這也是為什么xml數據容量大的原因。
下面,我們來學習一下怎么解析xml數據,這才是重點。
XML的解析方式有2種
下面將給出選擇方案
:(基于兩種方式的特點選擇)
XML解析方式的選擇建議
我們必須知道上面的這幾種方法各有什么特點,才會使用:
蘋果原生
NSXMLParser:SAX方式解析,使用簡單
第三方框架
libxml2:純C語言,默認包含在iOS SDK中,同時支持DOM和SAX方式解析GDataXML:DOM方式解析,由Google開發,基于libxml2
雖然libxml2可以同時支持dom和sax方式的解析,但是因為其使用麻煩,所以在實際開發中,并不常用,而是SAX方式解析大文件的時候使用NSXMLParser,DOM方式解析小文件的時候使用GDataXML或NSXMLParser。
XML解析的方式介紹過了,我們再來看看到底怎么使用他們吧。
使用NSXMLParser解析數據很簡單,你只需要傳遞過來XML數據,然后在NSXMLParser的代理方法里面解析就好了。這時候NSXMLParser的代理方法會當讀到XML文件的開頭和結尾,以及讀到元素標簽的開始和結尾的時候通知代理,并調用相應的代理方法來執行。為了防止有朋友不清楚哪里是XML文件的開頭和結尾,哪里是元素的開頭和結尾,這里給出一張圖來明確表示一下:
下面給出代碼如何開始和如何設置代理方法:
// 傳入XML數據,創建解析器NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];// 設置代理,監聽解析過程parser.delegate = self;// 開始解析[parser parse];
代理方法
當掃描到文檔的開始時調用(開始解析)- (void)parserDidStartDocument:(NSXMLParser *)parser當掃描到文檔的結束時調用(解析完畢)- (void)parserDidEndDocument:(NSXMLParser *)parser當掃描到元素的開始時調用(attributeDict存放著元素的屬性)- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict當掃描到元素的結束時調用- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName/** * 解析發生錯誤時調用 */- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError;
在獲取到網絡數據以后:
// 1.創建XML解析器NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];// 2.成為NSXMLParser的代理parser.delegate = self;// 3.開始解析XML[parser parse];
然后在代理方法中拿到數據:
/** * 開始解析XML文檔中的每一個元素時調用 */- (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轉換模型 [self.videos addObject:video];}
然后就可以拿到數據數組,進行各種顯示的操作了
1,GDataXML基于libxml2庫,得做以下配置
導入libxml2庫
設置libxml2的頭文件搜索路徑(為了能找到libxml2庫的所有頭文件)
在Head Search Path中加入/usr/include/libxml2
設置鏈接參數(自動鏈接libxml2庫)
在Other Linker Flags中加入-lxml2
由于GDataXML是非ARC的,因此得設置編譯參數
GDataXMLDocument:代表整個XML文檔
GDataXMLElement
代表文檔中的每個元素
使用attributeForName:方法可以獲得屬性值
在獲取到網絡數據以后:
// 1.加載所有的xml到內存中 GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data options:kNilOptions error:nil]; // 2.獲取根元素 GDataXMLElement *rootElement = doc.rootElement; // 3.從根元素中獲取所有子元素 NSArray *elements = [rootElement elementsForName:@"video"]; // 4.將子元素中的屬性轉換為模型 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是數據的數組 }
然后就可以拿到數據數組,進行各種顯示的操作了
如果還有哪里不懂的,
新聞熱點
疑難解答