ios开发-AVPlayer 音乐播放自定义经典例题

控制器部分.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

你可能感兴趣的:(ios-开发)