IOS开发之网络篇第一章:数据交换格式
网络通信最常用的数据通信格式是xml和Json,各有各的好处,不管怎样,这种的格式,我们在开发的过程中经常使用的,现在就这两种格式进行记录笔记,以下内容不做详细分析,只针对如何应用各种读写工具进行对xml和json内容的操作
xml
解析XML文件现在有两种主流的,SAX和DOM
- SAX-基于时间事件驱动,意思就是读取的过程中,是由上往下的读取xml文件,当遇到节点的时候,触发相应的事件,使用上比较快,缺点是不能修改文件内容
- DOM-以树状形式加载,加载后存放在内存当中,所以如果文件大,读取的时间就会比较长,但是可修改文件
IOS的SDK提供了两个框架,还有些第三方框架,这里只介绍2种NSXML和TBXML
- NSXML-它是用Object-C语言编写,只支持SAX解析框架
- libxml2
- TBXML-使用DOM的解析框架(据说很快,有时间测试一下)
- TouchXML
- KissXML
- TinyXML
- GDataXML
现在有一个xml文件,现在通过NSXML方式来读取,我们另外写了一个类,用于读写xml的
第一种介绍的是NSXML
NodeText.xml
<?xml version="1.0" encoding="UTF-8"?> <Notes> <Note id="1"> <Name>8点到</Name> <UserID>tony</UserID> </Note> <Note id="1"> <Name>8点到</Name> <UserID>tony</UserID> </Note> </Notes>
下面的这个类是是用作读写XML用的,必须使用委托NSXMLParserDelegate,这里有两个方法,一个是初次化initWithURL:需要提供文件地址,另外一个方法是parser,这个方法就是开始解析xml文件的入口
XMLReader.h文件
#import <Foundation/Foundation.h> @interface XmlReader : NSObject<NSXMLParserDelegate> @property(nonatomic)NSMutableDictionary *dict; -(id)initWithURL:(NSURL *)url; -(void)parser; @end
具体的实现如下
XMLReader.m,NSXMLParserDelegate委托包含很多个方法可以,这里主要复写了以下几个方法
-
- (void)parserDidStartDocument:(NSXMLParser *)parser
- 当文档开始的时候会调用,只读一次
-
- (void)parserDidEndDocument:(NSXMLParser *)parser
- 当文档解析结束的时候调用,只读一次
-
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
- 当节点开始的时候调用
-
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
- 当节点结束的时候调用
-
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
- 当读取到节点里面的字符串的时候调用
@interface XmlReader() @property(nonatomic)NSURL *url; @end @implementation XmlReader -(id)initWithURL:(NSURL *)url { self = [super init]; if (self) { self.url = url; } return self; } -(void)parser { NSXMLParser *parser = [[NSXMLParser alloc]initWithContentsOfURL:self.url]; parser.delegate = self; BOOL b = [parser parse]; } - (void)parserDidStartDocument:(NSXMLParser *)parser { self.dict = [[NSMutableDictionary alloc]init]; } // sent when the parser begins parsing of the document. - (void)parserDidEndDocument:(NSXMLParser *)parser { } - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict { NSLog(@"%@",elementName); } -(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { NSLog(@"%@",string); } -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { NSLog(@"%@",elementName); } @end
第二种介绍的是TBXML
这个是一个第三方提供的读取方式,所以需要导入代码工程,可以到https://github.com/71squared/TBXML下载源码,下载的zip包或者hub同步下载,我使用的是下载zip包,下载好后解压,会得到一大堆文件,但这里只需要提取TBXML.h和TBXML.m文件即可,把他们考到工程里面,直接使用即可。根据一些网上有些不同的经验之谈,有的因不支持ARC机制,而报的错,有的是因为工程没有导入libz.dylib包而出错,不管怎样,没有包的直接导入就行,不支持ARC就找找网络的文章就可以解决,我这里出现了另外一个情况,就是TBXML.h文件少导入了fundation包,所以导致报错了,没有找到NSObject
这些都配置好后,就可以使用了,这里我写了另外的一个类,用作读取信息xml用的,代码如下
XmlReaderTBXML.h文件
#import <Foundation/Foundation.h> #import "TBXML.h" @interface XmlReaderTBXML : NSObject @property (strong,nonatomic) NSMutableArray *notes; //开始解析方法 -(void)start; @end
XmlReaderTBXML.h文件
#import "XmlReaderTBXML.h" @implementation XmlReaderTBXML -(void)start { self.notes = [[NSMutableArray alloc]init]; TBXML *tbxml = [[TBXML alloc]initWithXMLFile:@"NodeTest.xml" error:nil]; TBXMLElement * root = tbxml.rootXMLElement; if (root) { TBXMLElement * noteElement = [TBXML childElementNamed:@"Note" parentElement:root]; while ( noteElement != nil) { NSMutableDictionary *dict = [NSMutableDictionary new]; TBXMLElement *CDateElement = [TBXML childElementNamed:@"CDate" parentElement:noteElement]; if ( CDateElement != nil) { NSString *CDate = [TBXML textForElement:CDateElement]; [dict setValue:CDate forKey:@"CDate"]; } TBXMLElement *ContentElement = [TBXML childElementNamed:@"Content" parentElement:noteElement]; if ( ContentElement != nil) { NSString *Content = [TBXML textForElement:ContentElement]; [dict setValue:Content forKey:@"Content"]; } TBXMLElement *UserIDElement = [TBXML childElementNamed:@"UserID" parentElement:noteElement]; if ( UserIDElement != nil) { NSString *UserID = [TBXML textForElement:UserIDElement]; [dict setValue:UserID forKey:@"UserID"]; } //ID属性 NSString *_id = [TBXML valueOfAttributeNamed:@"id" forElement:noteElement error:nil]; [dict setValue:_id forKey:@"id"]; [_notes addObject:dict]; noteElement = [TBXML nextSiblingNamed:@"Note" searchFromElement:noteElement]; } } NSLog(@"解析完成..."); self.notes = nil; } @end
在这个start方法中就是读取xml的过程,非常简单,就不作介绍了
JSON
Json是一个轻量级的数据交换格式,这个只是对比起XML来说的,在网络传输当中,JSON因为不像XML那样需要成双成对的节点结构,一个开节点,一个闭节点,所以它比XML的字节数会减少许多,Json的结构如下,主要由两个符号组成
- {}=字典Dictionary,{"Item_1":"LL","Item_2":123,"Item_3":true},在IOS里面,对Json的Key有格式要求,必须要双引号,不能是单引号,更不能没有引号,Key跟value之间以冒号(:)分割,两组键值对之间以逗号(,)相隔
- []=数组Array,["Item_1","Item_2","Item_3"],项与项之间以都好(,)相隔
这里解码的方式有以下几种,我们这里就只学NSJSONSerialization
- SBJSON
- TouchJSON
- YAJL
- JSONKit
- NextiveJson
- NSJSONSerialization ,它是在IOS 5.0后才被加入SDK中使用
这个是JSON格式的文件
JText.json
{ "Item_1":"测试1", "Item_2":"测试2", "Item_3":"测试3" }
通过以下代码就能获取到JSON内容
首先要把文件转换成NSData,其中第二行代码就是转换为NSData,第四行中就是主要的解析json内容的代码,其中一个参数是options,这里的常量参数有3种
- NSJSONReadingMutableContainers 一般都使用这个
- NSJSONReadingMutableLeaves 这个的用意不是很明确,网上说的都是笼统的,只是纸上谈兵,具体应用是怎样,好像没有一个说法,如果知道的同学可以评论一下
- NSJSONReadingAllowFragments 这个的用意不是很明确,网上说的都是笼统的,只是纸上谈兵,具体应用是怎样,好像没有一个说法,如果知道的同学可以评论一下
NSString *path = [[NSBundle mainBundle]pathForResource:@"JText" ofType:@"json"]; NSData *data = [[NSData alloc]initWithContentsOfFile:path]; NSError *err; id jsonOBj = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&err]; NSLog(@"%@",jsonOBj);
得到一个对象后,可以进行多态转换,就可以获取到里面的值
if ([jsonOBj isKindOfClass:[NSDictionary class]]){ NSDictionary *dictionary = (NSDictionary *)jsonOBj; }