由于256那边在完善基础功能和界面阶段,在想到新的功能前,同时学习或者复习一些其他内容,所以就从网络通信开始下手,而网络通信的数据xml和json自然也就需要了解了。
XML:
基本机构元素分为element、attribute、content,当然element里是可以嵌套childElement的,解析规范分为DOM(Document Object Model)(日后补充)和SAX(Simple API for XML)。
SAX解析器在解析XML文件的各个元素时会触发各种事件(或者说各种方法),可以在各种方法中对各元素数据进行处理,从而达到获取或修改XML数据的目的。
由于SAX解析器不用将整个XML数据存放在内存中(DOM的做法),所以占用内存极小,速度更快。
IOS SDK自带NSXMLParser和libxml2(日后补充)两种解析器(学习阶段现已IOS SDK为主,暂不考虑第三方)。
NSXMLParser
NSXMLParser解析属于委托事件处理,所以需要为NSXMLParser制定一个delegate对象,而该delegate对象需要实现NSXMLParserDeledate协议,协议方法(按需实现,不用全部实现)如下:
- -parserDidStartDocument: 开始解析XML文档时触发该方法。
- -parserDidEndDocument: 结束解析XML文档时触发该方法。
- -parser:didStartElement:namespaceURI:qualifiedName: 开始处理XML element时触发该方法。
- -parser:didEndElement:namespaceURI:qualifiedName: 结束处理XML element时触发该方法。
- -parser:resolveExternalEntityName:systemID: 开始处理外部实体时触发该方法。
- -parser:parserErrorOccurred: 解析出错时触发该方法。
- -parser:validationErrorOccurred: XML文档验证错误时触发该方法。
- -parser:foundCharacters: 解析XML文档遇到字符串内容是触发该方法。
- -parser:foundIgnorableWhitespace: 解析XML文档遇到空白时触发该方法。
- -parser:foundProcessingInstructionWithTarget:data: 解析XML文档的处理指令是触发该方法。
- -parser:foundComment: 处理XML文档的注释时触发该方法。
- -parser:foundCDATA: 处理XML文档的CDATA内容时触发该方法。
delegate头文件
//遵守NSXMLParserDelegate协议
@interface MyXMLPaserDelegate : NSObject <NSXMLPaserDelegate>
//定义NSMutableArray * cities保存数据
@property (nonatomic, strong) NSMutableArray * cities;
@end
delegate实现文件
@implementation MyXMLParserDelegate
//定义city来保存具体城市的天气数据
CityWeather * city;
//定义一个NSString * currentValue用来获取element的内容
NSString * currentValue;
//开始解析element时触发该方法
-(void)parser:(NSXMLParser *) parser didStartElement:(NSString *) elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *) attributeDict
{
//当解析的是rootElement时,说明开始解析第一层,此时可声明self.cities
if(elementName isEqualTo:@"cities")
{
self.cities = [[NSMutableArray alloc] init];
}else if(elementName isEqualTo:@"city") //如果是city element,则处理信息
{
city = [[CityWeather alloc] init];
city.weather = [attributeDict objectForKey:@"weather"];
}
}
//处理字符串时,将字符串保存起来,以便在之后的方法中相应赋值
-(void)parser:(NSXMLParser *) parser foundCharacters:(NSString *) content
{
//如果content不为空
if(content)
{
currentValue = content;
}
}
//当某element解析结束时触发该方法,为相应数据赋值处理
-(void)parser:(NSXMLParser *) parser didEndElement:(NSString *) elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *) qualifiedName
{
//如果是rootElement,则表示解析结束
if(elementName isEqualTo:@"cities")
{
return;
}else if (elementName isEqualTo:@"city") //如果是city,将city添加到cities中,再将city值nil,以便下次利用
{
[self.cities addobject:city];
city = nil;
}else //如果是非rootElement或city的其他element,如city的chileElement,则将childElement添加到city对应的属性值上。
{
[city setValue:currentValue forKey:elementName];
currentValue = nil;
}
}
@end
controller implementation
@implementation MyViewController
MyXMLParserDelegate * parserDelegate;
-(void)viewDidLoad
{
[super viewDidLoad];
//XML文件的URL地址
NSURL * XMLUrl = [[NSBundle mainBundle] URLForResource:@"cities" withExtension:@"xml"];
//获取NSXMLParser变量
NSXMLParser * parser = [[NSXMLParser alloc] initWithContentOfURL:XMLURL];
//创建NSXMLParserDelegate对象
parserDelegate = [[NSXMLParserDelegate alloc] init];
//将parserDelegate指定为parser的委托对象
parser.delegate = parserDelegate;
//开始解析
[parser parser];
//解析结果会保存在parserDelegate.cities中,之后想要调用数据时调用parserDelegate.cities即可
}
JSON
JSON主要有以下两种数据结构:
- 由key-value对组成的数据结构(OC中的NSDictionary,由{}表示)。
- 有序集合(OC中的NSArray,由[]或()表示)。
可使用NSJSONSerialization的如下方法来处理JSON数据:
- +JSONObjectWithData:options:error: 将制定的NSData中包含的JSON数据转换为Object-C对象。
- +JSONObjectWithStream:options:error: 将制定输入流中包含的JSON数据转换为Object-C对象。
- +dataWithJSONObject:options:error: 将制定的JSON对象转换为NSData对象。
- +writeJSONObject:toStream:options:error:将制定的JSON对象转换为JSON字符串输出到制定输出流。
+isValidJSONObject: 验证制定对象是否可以正常转换为JSON数据。
如下JSON数据:
{
"results":[
{
"location":{"id":"WX4FBXXFKE4F","name":"北京","country":"CN","path":"北京,北京,中国","timezone":"Asia/Shanghai","timezone_offset":"+08:00"},
"now":{"text":"中雨","code":"14","temperature":"16"},
"last_update":"2017-05-22T12:20:00+08:00"
}
]
}
可如此解析:
@implementation WeatherModel
@synthesize weather;
//用获取的含有JSON数据的NSDATA来创建WeatherModel的方法
+(id)initWithData:(NSData *) data
{
//由于JSON数据的第一层是用{},所以判断为NSDictionary数据,用NSJSONSerialization进行解析
NSDictionary * dict = [NSJSONSerialization JSONObjectWithData: data options:(NSJSONReadingMutableLeaves) error:nil];
return [[self alloc] initWithDic:dict];
}
-(id)initWithDic:(NSDictionary *) dict
{
self = [super init];
//第二层只有一对[],所以判断为一个NSArray数据
NSArray * results = [dict objectForKey:@"results"];
//第三层只有一对{},所以判断为一个NSDictionary数据
NSDictionary * result = [results lastObject];
NSDictionary * nowWeather = [result objectForKey:@"now"];
self.weather = [nowWeather objectForKey:@"text"];
//类似的可以将JSON中各数据写入WeatherModel的成员变量中,需要调用数据是,调用对应的成员变量即可
return self;
}