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

本文介绍了一个iOS音乐应用程序的开发过程,包括使用Objective-C语言、UIKit框架来构建用户界面,利用AVFoundation框架播放音乐,以及通过自定义的下载操作类实现音乐下载功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

控制器部分.h
#import <UIKit/UIKit.h>

@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 <Foundation/Foundation.h>

@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 <UIKit/UIKit.h>
#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 <Foundation/Foundation.h>
#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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值