XML解析

2017-02-08  本文已影响17人  952625a28d0d
#import "ViewController.h"
#import "Video.h"

@interface ViewController ()<NSXMLParserDelegate>

// MARK: -XML解析需要的素材
// 可变数组
@property (nonatomic,strong) NSMutableArray *videos;
// 当前解析的节点 -- 模型
@property (nonatomic, strong) Video *currentVideo;
// 拼接我们的字符串 -- 可变字符串
@property (nonatomic, copy) NSMutableString *elementStr;

@end

@implementation ViewController

- (NSMutableArray *)videos{
    if (!_videos) {
        _videos = [NSMutableArray array];
    }
    return _videos;
}

- (NSMutableString *)elementStr{
    if (!_elementStr) {
        _elementStr = [[NSMutableString alloc] init];
    }
    return _elementStr;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    [self loadData];
}

- (void)loadData{
    NSURL *url = [NSURL URLWithString:@""];
    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:1 timeoutInterval:10.0];
    [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
       
        // XML解析 -- 耗时操作
        NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
        // 设置代理 - 一旦解析器开始解析 都是通过代理来监听实现的
        parser.delegate = self;
        // 解析XML 解析器解析
        [parser parse];
    }];
}

#pragma mark - XML解析的代理方法
/**
 目标:解析成为一个包含多个Video的数组
 */
// 1.打开文档
- (void)parserDidStartDocument:(NSXMLParser *)parser{
    // 清空我们的数组
    [self.videos removeAllObjects];
}

// 2.开始节点
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict{
    NSLog(@"开始节点%@",elementName);
    // 判断是不是Video 如果是Video 创建Video对象
    if ([elementName isEqualToString:@"video"]) {
        // 新建video对象
        self.currentVideo = [[Video alloc] init];
        // 设置VideoId属性 用对象包装一下
        self.currentVideo.videoId = @([attributeDict[@"videoId"] intValue]);
    }
}

// 3.发现节点内容(一个节点可能会读取很多次) string 就是内容
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
    // 拼接字符串
    NSLog(@"发现节点内容%@",string);
    [self.elementStr appendString:string];
}

// 4.结束节点
/**
 KVC key value coding 键值编码 间接的设置值得方式
 cocoa 的一个大招
 */
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
    NSLog(@"结束节点名称%@",elementName);
    // 如果是name length imageUrl desc video
    if ([elementName isEqualToString:@"video"]) {
        // 如果是video 添加模型到数组
        [self.videos addObject:self.currentVideo];
    }else if (![elementName isEqualToString:@"videos"]){
        [self.currentVideo setValue:self.elementStr forKey:elementName];
    }
    // 清空字符串
    [self.elementStr setString:@""];
}
// 5.结束文档
- (void)parserDidEndDocument:(NSXMLParser *)parser{
    NSLog(@"结束文档");
}
// 6.如果出现了错误(只要是网络开发,就需要处理错误)
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{
    NSLog(@"发生错误%@",parseError);
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end
#import <Foundation/Foundation.h>

@interface Person : NSObject

// id 还是能用的 为了好看 用大写ID也是可以的
@property (nonatomic, strong) NSNumber *ID;

// kvc字符串判空
@property (nonatomic, copy) NSString *name;

// 技巧 这里使用NSNumber 而不使用基本数据类型 可以避免服务器返回null的时候崩溃
@property (nonatomic, strong) NSNumber *age;

@end
上一篇下一篇

猜你喜欢

热点阅读