IOS_XMLParser_JSONSerialization_MediaPlayer

裴嘉良
2023-12-01
H:/0727/01_XMLParser_JSONSerialization_MediaPlayer_localXML.xml
<?xml version="1.0" encoding="utf-8"?>
<videos><video id="1"><name>01.C语言-语法预览</name><length>320</length><videoURL>/itcast/videos/01.C语言-语法预览.mp4</videoURL><imageURL>/itcast/images/head1.png</imageURL><description>C语言-语法预览</description><teacher>MJ</teacher></video></videos>

H:/0727/01_XMLParser_JSONSerialization_MediaPlayer_Video.h
//
//  Video.h
//  Get XML & JSON
//
//  Created by apple on 13-7-27.
//  Copyright (c) 2013年 itcast. All rights reserved.
//
// 视频对象类,和网络请求返回的XML/JSON的数据结构一致

#import <Foundation/Foundation.h>

@interface Video : NSObject

@property (nonatomic, assign) NSInteger videoId;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) NSInteger length;
@property (nonatomic, strong) NSString *videoURL;
@property (nonatomic, strong) NSString *imageURL;
@property (nonatomic, strong) NSString *description;
@property (nonatomic, strong) NSString *teacher;

@end

H:/0727/01_XMLParser_JSONSerialization_MediaPlayer_Video.m
//
//  Video.m
//  Get XML & JSON
//
//  Created by apple on 13-7-27.
//  Copyright (c) 2013年 itcast. All rights reserved.
//

#import "Video.h"

@implementation Video

@end

H:/0727/01_XMLParser_JSONSerialization_MediaPlayer_VideoCell.h
//
//  VideoCell.h
//  Get XML & JSON
//
//  Created by apple on 13-7-27.
//  Copyright (c) 2013年 itcast. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface VideoCell : UITableViewCell

@property (weak, nonatomic) IBOutlet UIImageView *videoImage;
@property (weak, nonatomic) IBOutlet UILabel *videoName;
@property (weak, nonatomic) IBOutlet UILabel *teacherLabel;
@property (weak, nonatomic) IBOutlet UILabel *timeLabel;

@end

H:/0727/01_XMLParser_JSONSerialization_MediaPlayer_VideoCell.m
//
//  VideoCell.m
//  Get XML & JSON
//
//  Created by apple on 13-7-27.
//  Copyright (c) 2013年 itcast. All rights reserved.
//

#import "VideoCell.h"

@implementation VideoCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

@end

H:/0727/01_XMLParser_JSONSerialization_MediaPlayer_ViewController.h
//
//  ViewController.h
//  Get XML & JSON
//
//  Created by apple on 13-7-27.
//  Copyright (c) 2013年 itcast. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <NSXMLParserDelegate,UITableViewDataSource, UITableViewDelegate>

// 数据表格
@property (weak, nonatomic) IBOutlet UITableView *webDataTable;

// 加载XML数据
- (IBAction)loadXMLData:(id)sender;
// 加载JSON数据
- (IBAction)loadJSONData:(id)sender;

@end

H:/0727/01_XMLParser_JSONSerialization_MediaPlayer_ViewController.m
//  ViewController.m
//  Get XML & JSON
//  Created by apple on 13-7-27.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import "ViewController.h"
#import "Video.h"
#import "VideoCell.h"
#import <MediaPlayer/MediaPlayer.h>
// 引入头文件的目的是要播放
// 播放我们需要一个播放的控制器来替我们完成工作
// 播放控制器,我们要定义一个成员变量来实现
@interface ViewController ()
{
    // 有服务器返回的数据数组
    NSMutableArray      *_dataList;  
    // 使用一个可变字符串记录解析结果
    NSMutableString     *_elementString;
    // 当前解析的Video节点
    Video               *_currentVideo;
    // 视频播放控制器
    MPMoviePlayerController *_player;
}
@end
@implementation ViewController
#pragma mark - 数据表格DataSource代理方法
// 1. 返回行数,即Vedio对象数组的长度
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [_dataList count];
}
// 2. 单元格
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"videoCell";
    // 使用了自定义的cell
    VideoCell *cell = (VideoCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];    
    if (cell == nil) {
        cell = [[VideoCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }
    // 给单元格属性赋独一无二的值
    Video *video = _dataList[indexPath.row];
    // 赋值开始
    [cell.videoName setText:video.name];
    [cell.teacherLabel setText:video.teacher];
    // 用字符串进行转换,将时长,由秒,转成分钟和秒
    NSString *timeString = [NSString stringWithFormat:@"%02d:%02d", video.length / 60, video.length % 60];
    [cell.timeLabel setText:timeString];    
    // 1. URL(拼接)
    // 2. 通过url得到图片的Data
    // 3. 通过data创建图片Image
    // 因为服务器的地址,有可能会变化,因此,在实际应用中,我们经常会记录的是相对地址。
    // 如果我们换了服务器,我只要改一下ip地址,同时把其他相关资源,按照原有路径配置即可。
    // 获得URL之前,需要先拼接一下完整的服务器地址
    NSString *serverAddress = [NSString stringWithFormat:@"http://192.168.1.24/~apple%@", video.imageURL];
    NSURL *imageUrl = [NSURL URLWithString:serverAddress];
    NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
    UIImage *image = [UIImage imageWithData:imageData];
    [cell.videoImage setImage:image];
    return cell;
}

#pragma mark - 数据表格TableDelegate代理方法
// 3.didSelectRowAtIndexPath选中单元格,开始播放视频
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    Video *video = _dataList[indexPath.row];
    NSLog(@"%@", video.videoURL);
    // 也需要加一个服务器的头
    NSString *videoURLString = [NSString stringWithFormat:@"http://192.168.1.24/~apple%@", video.videoURL];    
    // 下面我们要播放了
    // 有中文地址的时候,一定要添加百分号AddingPercent
    NSURL *videoURL = [NSURL URLWithString:[videoURLString 
			stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    // 视频播放对象
    if (_player == nil) {
        _player = [[MPMoviePlayerController alloc]initWithContentURL:videoURL];
    } else {
        [_player setContentURL:videoURL];
    }
    // 设置播放器视图边框,跟当前的试图控制器大小一致
    [_player.view setFrame:self.view.bounds];
    
    // 将视频播放控制器视图添加到当前视图
    [self.view addSubview:_player.view];
    
    // 注册一个播放结束的通知
    // 注,这里的通知只是监控了一下退出全屏的事件,而不是视频播放的真正控制。
#warning 上网找一下视频播放相关的控制代码
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(movieFinishedCallback:)
			name:MPMoviePlayerDidExitFullscreenNotification object:_player];
    
    // 开始播放
    [_player play];
    // 全屏播放
    [_player setFullscreen:YES];
}

#pragma mark -响应按钮点击,开启XML数据解析
- (IBAction)loadXMLData:(id)sender
{
    // 1. 确定地址
    NSString *urlString = @"http://192.168.1.24/~apple/itcast/videos.php?format=xml";
    NSURL *url = [NSURL URLWithString:urlString];
    
    // 如果网络数据量非常大,可以用本地文件进行测试,测试完成之后,再用网络地址替换!
    NSString *urlFileString = [[NSBundle mainBundle]pathForResource:@"localXML.xml" ofType:nil];
    NSURL *urlFile = [NSURL fileURLWithPath:urlFileString];
    NSLog(@"url File %@", urlFile);

    // 简单的方法,就可以通过NSData的init方法,直接加载数据
    NSData *data = [[NSData alloc]initWithContentsOfURL:url];
    
//    NSLog(@"接收到的数据%@", data);
    NSString *result = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"接收到的数据%@", result);
    
    // 在此之前需要先得到数据!
    // 1. 创建NSXMLPaser的实例,并传入服务器“数据”?
    NSXMLParser *paser = [[NSXMLParser alloc]initWithData:data];

    // 2. 定义解析器代理
    [paser setDelegate:self];
    
    // 3. 解析器解析
    [paser parse];
    
    // 4. 通过代理方法进行解析    
}

#pragma mark - XML解析器代理方法
// 1. didStartElement开始解析元素结点
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
			namespaceURI:(NSString *)namespaceURI 
			qualifiedName:(NSString *)qName 
			attributes:(NSDictionary *)attributeDict
{       
    // 1. 从"video"开始,意味着新的视频对象要开始初始化,并填充数据了    
    if ([elementName isEqualToString:@"video"]) {
        // 下面就是新的节点了
        // 我们需要一个video对象来记录所有解析结果
		//初始化一个新的video对象,用于接收数据
		_currentVideo = [[Video alloc]init];            
        NSLog(@"id属性:%@", attributeDict);        
        [_currentVideo setVideoId:[attributeDict[@"id"]integerValue]];
    }
}

// 2. 文本节点
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    [_elementString appendString:string];
}

//3.didEndElement结束结点,通过判断结点名,将临时文本串,赋值给对象的相应属性
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
		namespaceURI:(NSString *)namespaceURI
		qualifiedName:(NSString *)qName
{
    NSLog(@"结束某个节点 %@ %@ 当前对象:%@", elementName, _elementString, _currentVideo);
    // 可以通过elementName来设置节点内容
    /***
     * 注意:这个位置不能直接使用成员赋值,因为成员变量是一个指针。
     */
    NSString *string = [NSString stringWithString:_elementString];
    NSLog(@"%p %p", &string, &_elementString);
    
    if ([elementName isEqualToString:@"name"]) {
        [_currentVideo setName:string];
    } else if ([elementName isEqualToString:@"length"]) {
        [_currentVideo setLength:string.integerValue];
    } else if ([elementName isEqualToString:@"videoURL"]) {
        [_currentVideo setVideoURL:string];
    } else if ([elementName isEqualToString:@"imageURL"]) {
        [_currentVideo setImageURL:string];
    } else if ([elementName isEqualToString:@"description"]) {
        [_currentVideo setDescription:string];
    } else if ([elementName isEqualToString:@"teacher"]) {
        [_currentVideo setTeacher:string];
    } else if ([elementName isEqualToString:@"video"]) {
        // video节点结束,代表已经填充好数据,将临时video对象添加到对象数组!
        [_dataList addObject:_currentVideo];
    }
    
    // 清空临时字符串,为下一次找到字符时,为拼接文本作准备
    [_elementString setString:@""];
}

// 以上三步会不断地重复执行,直到遍历完所有节点
// 4. 开始解析XML文档
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
    NSLog(@"开始解析XML文档");
    
    // 定义了可变字符串成员变量,我们需要初始化,可以在文档开始的时候,做一个懒加载
    // 初始化成员变量
    if (_elementString == nil) {
        _elementString = [[NSMutableString alloc]init];
    }
    
    // 可以在这儿,初始化对象数组
    if (_dataList == nil) {
        _dataList = [NSMutableArray array];
    }   
}

// 5. 解析XML文档完成
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
    NSLog(@"解析XML文档完成 %@", _dataList);
    
    for (Video *video in _dataList) {
        NSLog(@"%d %@ %@ %@", video.videoId, video.name, video.videoURL, video.imageURL);
    }
}

// 6. 解析出错localizedDescription
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
    NSLog(@"解析出错 %@", parseError.localizedDescription);
}

#pragma mark - 响应点击,开启JSON数据解析NSJSONSerialization
- (IBAction)loadJSONData:(id)sender
{
    // 解析需要数据,需要从服务器来的数据!
    NSURL *url = [NSURL URLWithString:@"http://192.168.1.24/~apple/itcast/videos.php?format=json"];
    NSData *data = [[NSData alloc]initWithContentsOfURL:url];
    
    // 数据获取到了,我们需要进行解析了
    // 要根据JSON字符串的根式,来确定,到底解析成为什么数据格式!!!
    // "[" 表示数组 "{" 表示对象
    NSArray *array = [NSJSONSerialization JSONObjectWithData:data 
						options:NSJSONReadingAllowFragments error:nil];
    
    // 很重要的技巧!
    // 我们把数组存到磁盘去!
    NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *arrayPath = [documents[0]stringByAppendingPathComponent:@"array.plist"];
    [array writeToFile:arrayPath atomically:YES];   
    // 看到结果之后,再动手!
    
    // 1. 要初始化数组
    // 为什么要判断_dataList = nil?
    // 如果有了我们需要把数组清空
    if (_dataList == nil) {
        _dataList = [NSMutableArray array];
    } else {
        [_dataList removeAllObjects];
    }
    
    // 2. 循环遍历刚刚解析出来的array
    // 3. 逐一生成video对象,并插入_dataList;
    // 开始遍历
    for (NSDictionary *dict in array) {
        Video *video = [[Video alloc]init];
        [video setName:dict[@"name"]];
        [video setLength:[dict[@"length"]integerValue]];
        [video setVideoURL:dict[@"videoURL"]];
        [video setImageURL:dict[@"imageURL"]];
        [video setDescription:dict[@"description"]];
        [video setTeacher:dict[@"teacher"]];
        [_dataList addObject:video];
    }
    NSLog(@"解析数据的个数aaaa %d", _dataList.count);
    [_webDataTable reloadData];
}

@end

H:/0727/02_XML_JSON_BUG_Video.h
//
//  Video.h
//  Get XML & JSON
//
//  Created by apple on 13-7-27.
//  Copyright (c) 2013年 itcast. All rights reserved.
//
// 视频对象类,和网络请求返回的XML/JSON的数据结构一致

#import <Foundation/Foundation.h>

@interface Video : NSObject

@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) NSInteger length;
@property (nonatomic, strong) NSString *videoURL;
@property (nonatomic, strong) NSString *imageURL;
@property (nonatomic, strong) NSString *description;
@property (nonatomic, strong) NSString *teacher;

@end

H:/0727/02_XML_JSON_BUG_Video.m
//
//  Video.m
//  Get XML & JSON
//
//  Created by apple on 13-7-27.
//  Copyright (c) 2013年 itcast. All rights reserved.
//

#import "Video.h"

@implementation Video

@end

H:/0727/02_XML_JSON_BUG_VideoCell.h
//
//  VideoCell.h
//  Get XML & JSON
//
//  Created by apple on 13-7-27.
//  Copyright (c) 2013年 itcast. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface VideoCell : UITableViewCell

@property (weak, nonatomic) IBOutlet UIImageView *videoImage;
@property (weak, nonatomic) IBOutlet UILabel *videoName;
@property (weak, nonatomic) IBOutlet UILabel *teacherLabel;
@property (weak, nonatomic) IBOutlet UILabel *timeLabel;

@end

H:/0727/02_XML_JSON_BUG_VideoCell.m
//
//  VideoCell.m
//  Get XML & JSON
//
//  Created by apple on 13-7-27.
//  Copyright (c) 2013年 itcast. All rights reserved.
//

#import "VideoCell.h"

@implementation VideoCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

@end

H:/0727/02_XML_JSON_BUG_ViewController.h
//
//  ViewController.h
//  Get XML & JSON
//
//  Created by apple on 13-7-27.
//  Copyright (c) 2013年 itcast. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <NSXMLParserDelegate>

// 加载XML数据
- (IBAction)loadXMLData:(id)sender;
// 加载JSON数据
- (IBAction)loadJSONData:(id)sender;

@end

H:/0727/02_XML_JSON_BUG_ViewController.m
//  ViewController.m
//  Get XML & JSON
//  Created by apple on 13-7-27.
//  Copyright (c) 2013年 itcast. All rights reserved.
#import "ViewController.h"
#import "Video.h"
@interface ViewController ()
{
    // 对象数组
    NSMutableArray      *_dataList;  
    // 临时文本字符串
    NSMutableString     *_elementString;
    // 当前解析的Video对象
    Video               *_currentVideo;
}
@end
@implementation ViewController
- (void)viewDidLoad
{
    [super viewDidLoad];	
}
#pragma mark - 响应点击事件,启动XML数据解析
- (IBAction)loadXMLData:(id)sender
{
    // 要得到数据,数据是怎么得到的?从网络上GET下来的,得到数据是不是网络访问
    // 1. 确定地址
    NSString *urlString = @"http://192.168.1.24/~apple/itcast/videos.php?format=xml";
    NSURL *url = [NSURL URLWithString:urlString];
    // 简单的方法,就可以通过NSData的initWithContentsOfURL方法,直接加载数据
    NSData *data = [[NSData alloc]initWithContentsOfURL:url];
//    NSLog(@"接收到的数据%@", data);
    NSString *result = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
//    NSLog(@"接收到的数据编码后:%@", result);
    // 在此之前需要先得到数据!
    // 1. 创建NSXMLPaser的实例,参数必须传入从服务器接收的Data“数据”?
    NSXMLParser *paser = [[NSXMLParser alloc]initWithData:data];
    // 2. 定义解析器代理为当前控制器
    [paser setDelegate:self];
    // 3. 启动解析器解析,其他事情通过代理去完成
    [paser parse];
}
#pragma mark - 重点!!!XML解析器代理方法
// 1. didStartElement开始解析元素节点,主要任务:初始化一个空对象
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName 
		namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 
		attributes:(NSDictionary *)attributeDict
{
    NSLog(@"开始解析元素:%@",elementName);
    // 1. 从"video"开始,意味着新的节点开始了   
    if ([elementName isEqualToString:@"video"]) {
        // 下面就是新的节点了
        // 我们需要一个video对象来记录所有解析结果
        // 开始解析的时候,不知道完整对象内容,所以,我们也同样需要一个成员变量
        // 初始化当前节点
        _currentVideo = [[Video alloc]init];
		//从字典属性attributes中attributeDict取出ID,为_currentVideo的成员变量id赋值
    }
}
// 2. foundCharacters,可反复执行,文本节点,任务只是拼接字符串appendString
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    // 一个节点,会解析多次!我们需要想办法解决这个问题
    // 怎么解决?是不是需要拼接字符串啊

 类似资料:

相关阅读

相关文章

相关问答