控制器部分.h
#import
@import
AVFoundation;
@interface
MYYViewController :
UIViewController
<
UITableViewDelegate
,
UITableViewDataSource
]] >
@property
(
nonatomic
,
strong
)
IBOutlet
UITableView
*tableView;
@end
实现部分.m
#import
"MYYViewController.h"
#import
"MYYDownLoadOperation.h"
#import
"MYYTableViewCell.h"
@interface
MYYViewController
()
//创建可变数组对象,存储歌曲信息
@property
(
nonatomic
,
strong
)
NSMutableArray
*songList;
//创建操作管理对象
@property
(
nonatomic
,
strong
)
NSOperationQueue
*downloaQueue;
//播放音乐对象
@property
(
nonatomic
,
strong
)
AVPlayer
*player;
@end
@implementation
MYYViewController
-(
void
)awakeFromNib{
[
super
awakeFromNib
];
self
.
songList
= [[
NSMutableArray
alloc
]
init
];
//创建对象
self
.
downloaQueue
= [[
NSOperationQueue
alloc
]
init
];
}
- (
void
)viewDidLoad
{
[
super
viewDidLoad
];
// Do any additional setup after loading the view, typically from a nib.
#define KURLFormat @
"http://115.28.227.1/student/beijing/class_beijing_28/media/%@.mp3"
//循环添加60个音乐的地址
for
(
NSInteger
i =
1
; i<=
60
; i++) {
MYYMusicInfo
*item = [[
MYYMusicInfo
alloc
]
init
];
NSString
*url = [[
NSString
alloc
]
initWithFormat
:
KURLFormat
,
@(
i
)
.
description
];
item.
url
= url;
item.
musicName
=
@(
i
)
.
description
;
item.
progress
=
0.0f
;
[
self
.
songList
addObject
:item];
}
}
- (
void
)didReceiveMemoryWarning
{
[
super
didReceiveMemoryWarning
];
// Dispose of any resources that can be recreated.
}
#pragma mark-table
-(
NSInteger
)tableView:(
UITableView
*)tableView numberOfRowsInSection:(
NSInteger
)section{
return
self
.
songList
.
count
;
}
-(
UITableViewCell
*)tableView:(
UITableView
*)tableView cellForRowAtIndexPath:(
NSIndexPath
*)indexPath{
MYYTableViewCell
*cell =
nil
;
cell = (
MYYTableViewCell
*)[tableView
dequeueReusableCellWithIdentifier
:
@"song"
forIndexPath
:indexPath];
MYYMusicInfo
*item =
self
.
songList
[indexPath.
row
];
item.
delegate
= cell;
//单元格刷新
cell.
item
= item;
return
cell;
}
//单元格消失时,设定音乐对象的代理对象为空
-(
void
)tableView:(
UITableView
*)tableView didEndDisplayingCell:(
UITableViewCell
*)cell forRowAtIndexPath:(
NSIndexPath
*)indexPath{
MYYMusicInfo
*item =
self
.
songList
[indexPath.
row
];
item.
delegate
=
nil
;
}
-(
void
)tableView:(
UITableView
*)tableView didSelectRowAtIndexPath:(
NSIndexPath
*)indexPath{
[tableView
deselectRowAtIndexPath
:indexPath
animated
:
YES
];
//点击要先置空 (进行下一个的时候)
/*
[self.player pause];
self.player = nil;
NSURL *songURL = [NSURL URLWithString:self.songList[indexPath.row]];
self.player =[[AVPlayer alloc]initWithURL:songURL];
[self.player play];
*/
MYYMusicInfo
*item =
self
.
songList
[indexPath.
row
];
//假设当前音乐处于下载状态时,就不在进行下载了
if
(item.
isDownloading
) {
return
;
}
//假设当前的音乐处于下载状态时,就不用再下载了
if
(!item.
isDownloading
&& item.
isFinished
) {
//下载完成后,因为已经修改url为本地的地址了
self
.
player
= [[
AVPlayer
alloc
]
initWithURL
:[
NSURL
fileURLWithPath
:item.
url
]];
//播放音乐
[
self
.
player
play
];
return
;
}
MYYDownLoadOperation
*downLoadOp = [[
MYYDownLoadOperation
alloc
]
initWithInfo
:item ];
[
self
.
downloaQueue
addOperation
:downLoadOp];
}
//
// UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
//
// [tableView registerNib:[UINib nibWithNibName:@"MYYTableViewCell" bundle:nil] forCellReuseIdentifier:@"song"];
//
// [tableView registerClass:NSClassFromString(@"MYYTableViewCell") forCellReuseIdentifier:@"song"];
//
// tableView.delegate = self;
// tableView.dataSource = self;
//
// [self.view addSubview:tableView];
//}
@end
音乐对象.h
#import
@class
MYYMusicInfo
;
@protocol
MYYMusicProtocol<
NSObject
>
-(
void
)musicDownLoadRefresh:(
MYYMusicInfo
*)music;
@end
@interface
MYYMusicInfo :
NSObject
@property
(
nonatomic
,
strong
)
NSString
*url;
@property
(
nonatomic
,
assign
)
CGFloat
progress;
//歌曲名称
@property
(
nonatomic
,
strong
)
NSString
*musicName;
@property
(
nonatomic
,
weak
)
id
<
MYYMusicProtocol
>delegate;
@property
(
nonatomic
,
assign
)
BOOL
isDownloading;
@property
(
nonatomic
,
assign
)
BOOL
isFinished;
@end
音乐类的实现
#import
"MYYMusicInfo.h"
@implementation
MYYMusicInfo
- (
instancetype
)init
{
self
= [
super
init
];
if
(
self
) {
self
.
isDownloading
=
NO
;
self
.
isFinished
=
NO
;
}
return
self
;
}
-(
void
)setProgress:(
CGFloat
)progress{
_progress
= progress;
//通知代理对象
[
self
.
delegate
musicDownLoadRefresh
:
self
];
}
@end
自定义单元格
#import
#import
"MYYMusicInfo.h"
@interface
MYYTableViewCell :
UITableViewCell
<
MYYMusicProtocol
>
@property
(
nonatomic
,
strong
)
IBOutlet
UIView
*progressView;
@property
(
nonatomic
,
strong
)
IBOutlet
UILabel
*nameLabel;
@property
(
nonatomic
,
strong
)
IBOutlet
UILabel
*progressLabel;
@property
(
nonatomic
,
strong
)
MYYMusicInfo
*item;
@end
.m
#import
"MYYTableViewCell.h"
@implementation
MYYTableViewCell
- (
instancetype
)initWithCoder:(
NSCoder
*)coder
{
self
= [
super
initWithCoder
:coder];
if
(
self
) {
;
}
return
self
;
}
- (
void
)awakeFromNib
{
// Initialization code
}
- (
void
)setSelected:(
BOOL
)selected animated:(
BOOL
)animated
{
[
super
setSelected
:selected
animated
:animated];
// Configure the view for the selected state
}
-(
void
)musicDownLoadRefresh:(
MYYMusicInfo
*)music{
//修改进度视图的宽度
CGRect
rect =
self
.
progressView
.
frame
;
rect.
size
.
width
= music.
progress
*
320
;
self
.
progressView
.
frame
= rect;
NSLog
(
@"%@"
,
NSStringFromCGRect
(rect));
self
.
nameLabel
.
text
= music.
musicName
;
//修改进度标签的文字
self
.
progressLabel
.
text
= [
NSString
stringWithFormat
:
@"%.2f"
,music.
progress
*
100
];
NSLog
(
@"%.2f"
,music.
progress
*
100
);
}
-(
void
)setItem:(
MYYMusicInfo
*)item{
if
(
_item
== item) {
return
;
}
_item
= item;
//刷新
[
self
musicDownLoadRefresh
:
_item
];
}
@end
下载音乐
#import
#import
"MYYMusicInfo.h"
//下载的功能
@interface
MYYDownLoadOperation :
NSOperation
<
NSURLConnectionDataDelegate
]] >
//添加一个存储的属性
@property
(
nonatomic
,
strong
)
MYYMusicInfo
*musicInfo;
-(
instancetype
)initWithInfo:(
MYYMusicInfo
*)musicInfo;
@end
。m
#import
"MYYDownLoadOperation.h"
@implementation
MYYDownLoadOperation
{
//用来拼接下载到的每个片段的数据
NSMutableData
*mutableData;
//声明bool值 用来判断当前是否在下载,如果下载runloop一直存在,结束后,runloop消失
BOOL
isDownLoading;
//用来存储整个文件的大小
NSInteger
maxLength;
}
-(
instancetype
)initWithInfo:(
MYYMusicInfo
*)musicInfo
{
self
= [
super
init
];
if
(
self
) {
self
.
musicInfo
= musicInfo;
}
return
self
;
}
-(
void
)main{
//只有一进来就认为开始下载
self
.
musicInfo
.
isDownloading
=
YES
;
//将字符串转换成路径对象
NSURL
*url = [
NSURL
URLWithString
:
self
.
musicInfo
.
url
];
//响应
NSURLRequest
*request = [
NSURLRequest
requestWithURL
:url];
[
NSURLConnection
connectionWithRequest
:request
delegate
:
self
];
//只要再下载中 ,runloop就一直存在
while
(
self
.
musicInfo
.
isDownloading
)
{
[[
NSRunLoop
currentRunLoop
]
runUntilDate
:[
NSDate
distantFuture
]];
}
}
//客户端的接收到服务器的响应
-(
void
)connection:(
NSURLConnection
*)connection didReceiveResponse:(
NSURLResponse
*)response{
mutableData
= [[
NSMutableData
alloc
]
init
];
//能够直接强行转的原因,就是我们在发送请求的时候接收了http协议
NSHTTPURLResponse
*httpRespone = (
NSHTTPURLResponse
*)response;
//响应中存储的信息
NSDictionary
*dictionary = [httpRespone
allHeaderFields
];
//http协议中规定了很多的关键字,其中content-length 就是代表文件的大小
maxLength
= [dictionary[
@"Content-Length"
]
integerValue
];
}
//客户端每次接收到的数据片段数据之后都会执行的方法
-(
void
)connection:(
NSURLConnection
*)connection didReceiveData:(
NSData
*)data{
[
mutableData
appendData
:data];
CGFloat
progess = (
CGFloat
)
mutableData
.
length
/
maxLength
;
//修改下载的音乐对象的进度....
self
.
musicInfo
.
progress
= progess;
}
//下载完成的状态
-(
void
)connectionDidFinishLoading:(
NSURLConnection
*)connection{
//下载完成,修改下载状态 = NO
self
.
musicInfo
.
isDownloading
=
NO
;
self
.
musicInfo
.
isFinished
=
YES
;
//写入文件。。。。
NSArray
*document =
NSSearchPathForDirectoriesInDomains
(
9
,
1
,
1
);
NSString
*documentPath = document[
0
];
NSString
*filePath = [documentPath
stringByAppendingFormat
:
@"/%@.mp3"
,
self
.
musicInfo
.
musicName
];
//下载完成后替换成本地链接.....
self
.
musicInfo
.
url
= filePath;
//正确的写入方法
[
mutableData
writeToFile
:filePath
atomically
:
YES
];
}
//下载失败的回调函数
-(
void
)connection:(
NSURLConnection
*)connection didFailWithError:(
NSError
*)error{
self
.
musicInfo
.
isDownloading
=
NO
;
}
@end