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
{
// 一个节点,会解析多次!我们需要想办法解决这个问题
// 怎么解决?是不是需要拼接字符串啊