基于AVAudioPlayer的简易播放器

MusicHandle.h

// #import <Foundation/Foundation.h> // #import "MusicModel.h" / @interface MusicHandle : NSObject // 单例类 /+ (MusicHandle *)defaultHandle; // 添加一个 model对象 /- (void)addObjectWithModel:(MusicModel *)model; // 查询出有多少个 model /- (NSInteger)musicCount; // 根据 index找出 model /- (MusicModel *)modelWithIndex:(NSInteger)index; @end

MusicHandle.m

/#import "MusicHandle.h" @interface MusicHandle () @property (nonatomic, strong) NSMutableArray *dataArray; @end @implementation MusicHandle // 单例类 /+ (MusicHandle *)defaultHandle { static MusicHandle *musicHandel = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ if (musicHandel == nil) { musicHandel = [[MusicHandle alloc] init]; musicHandel.dataArray = [NSMutableArray array]; } }); return musicHandel; } // 添加一个 model对象 /- (void)addObjectWithModel:(MusicModel *)model { [self.dataArray addObject:model]; } // 查询出有多少个 model /- (NSInteger)musicCount { return self.dataArray.count; } // 根据 index 找出 model /- (MusicModel *)modelWithIndex:(NSInteger)index { return self.dataArray[index]; } @end

MusicModel.h

#import <Foundation/Foundation.h> @interface MusicModel : NSObject @property (nonatomic, copy) NSString *musicName; @property (nonatomic, copy) NSString *musicType; @end

MusicListViewController.h

//#import <UIKit/UIKit.h> @interface MusicPlayerViewController : UIViewController @property (nonatomic, assign) NSInteger musicIndex; @end

MusicListViewController.m

`
//#import "MusicListViewController.h"
//#import "MusicPlayerViewController.h"
//#import "LabelTableViewCell.h"
//#import "MusicModel.h"
//#import "MusicHandle.h"
//#define kColor arc4random() % 256 / 255.0
@interface MusicListViewController ()<UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, strong) UITableView *tableView;
@end
@implementation MusicListViewController
//- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.tableView = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds style:(UITableViewStylePlain)];
self.tableView.dataSource = self;

self.tableView.delegate = self;
self.tableView.separatorColor = [UIColor redColor];
[self.tableView registerClass:[LabelTableViewCell class] forCellReuseIdentifier:@"cell_id"];
[self.view addSubview:self.tableView];
// 添加3首歌曲
MusicModel *model = [[MusicModel alloc] init];
model.musicName = @"情非得已";
model.musicType = @"mp3";
MusicModel *model1 = [[MusicModel alloc] init];
model1.musicName = @"林俊杰-背对背拥抱";
model1.musicType = @"mp3";
MusicModel *model2 = [[MusicModel alloc] init];
model2.musicName = @"梁静茹-偶阵雨";
model2.musicType = @"mp3";
[[MusicHandle defaultHandle] addObjectWithModel:model];
[[MusicHandle defaultHandle] addObjectWithModel:model1];
[[MusicHandle defaultHandle] addObjectWithModel:model2];
self.navigationItem.title = @"The Song List";
[self.navigationController.navigationBar setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:26], NSForegroundColorAttributeName:[UIColor whiteColor]}];
self.navigationController.navigationBar.barStyle = UIBarStyleBlackTranslucent;

}
//- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Auto adjusting tableView's number of rows
return [[MusicHandle defaultHandle] musicCount];
}
//- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
LabelTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell_id" forIndexPath:indexPath];
cell.songLabel.font = [UIFont systemFontOfSize:21];
MusicModel *model = [[MusicHandle defaultHandle] modelWithIndex:indexPath.row];
cell.songLabel.text = model.musicName;
cell.backgroundColor = [UIColor colorWithRed:kColor green:kColor blue:kColor alpha:0.5];
return cell;
}
//- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MusicPlayerViewController *musicPlayVC = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"musicPlayVC"];
musicPlayVC.musicIndex = indexPath.row;
[self.navigationController pushViewController:musicPlayVC animated:YES];
}
//- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
`

LabelTableViewCell.h

//#import <UIKit/UIKit.h> @interface LabelTableViewCell : UITableViewCell @property (nonatomic, strong) UILabel *songLabel; @end

LabelTableViewCell.m

//#import "LabelTableViewCell.h" @implementation LabelTableViewCell //- (void)awakeFromNib { // Initialization code } //- (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state } //- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { self.songLabel = [[UILabel alloc] initWithFrame:CGRectZero]; self.songLabel.textAlignment = NSTextAlignmentCenter; [self.contentView addSubview:self.songLabel]; } return self; } //- (void)layoutSubviews { self.songLabel.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height); } @end

MusicPlayerViewController.h

//#import <UIKit/UIKit.h> @interface MusicPlayerViewController : UIViewController @property (nonatomic, assign) NSInteger musicIndex; @end

MusicPlayerViewController.m

`
//#import "MusicPlayerViewController.h"
//#import "MusicHandle.h"
//#import "MusicModel.h"
//#import <AVFoundation/AVFoundation.h>
@interface MusicPlayerViewController ()<UITableViewDataSource, UITableViewDelegate>
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (weak, nonatomic) IBOutlet UISlider *volumnSlider;
@property (weak, nonatomic) IBOutlet UISlider *timeSlider;
@property (weak, nonatomic) IBOutlet UILabel *currentTiemLabel;
@property (weak, nonatomic) IBOutlet UILabel *timeLabel;
// 记录播放状态
@property (nonatomic, assign) BOOL isPlay;
// 音频播放器
@property (nonatomic, strong) AVAudioPlayer *audioPlayer;
// 定时器
@property (nonatomic, strong) NSTimer *timer;
@end
@implementation MusicPlayerViewController
//- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// 导航栏标题
self.navigationItem.title = @"MusicPlayerViewController";
// 获取到一个需要播放的 model
MusicModel *model = [[MusicHandle defaultHandle] modelWithIndex:self.musicIndex];
// 获取音频的地址
NSString *pathString = [[NSBundle mainBundle] pathForResource:model.musicName ofType:model.musicType];
// 音频的 data
NSData *data = [NSData dataWithContentsOfFile:pathString];
// 根据音频的 data 创建一个 AVAudioPlayer对象
self.audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:nil];
// 记录播放初始状态
self.isPlay = NO;
// 注册tableViewCell
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell_id"];
// 让滑动条的值和音乐播放器的音量关联, 默认值为1(最大)
self.volumnSlider.value = self.audioPlayer.volume;
// 获取歌曲的持续时间
CGFloat time = self.audioPlayer.duration;
NSInteger minutes = (NSInteger)time / 60;
NSInteger seconds = (NSInteger)time % 60;
// 让右边label 的值置为歌曲的总时长
self.timeLabel.text = [NSString stringWithFormat:@"%02ld:%02ld", minutes, seconds];
// 设置控制音量的滑动条的渲染颜色
self.volumnSlider.minimumTrackTintColor = [UIColor blueColor];
self.volumnSlider.maximumTrackTintColor = [UIColor blueColor];
// 设置控制时间进度的滑动条的值为歌曲的时长
self.timeSlider.maximumValue = self.audioPlayer.duration;
// 设置控制时间的滑动条的渲染颜色
self.timeSlider.maximumTrackTintColor = [UIColor redColor];
// 让滑动条的进度与音乐的播放进度一致
self.timeSlider.value = self.audioPlayer.currentTime;
// 导航栏按钮
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Return" style:(UIBarButtonItemStyleDone) target:self action:@selector(barButtonItemClicked)];
}
// 点击按钮切回歌曲清单列表, 并暂停播放
//- (void)barButtonItemClicked {
[self.audioPlayer stop];
[self.navigationController popViewControllerAnimated:YES];
}
//- (void)timeChange {
// 显示时间进度
self.currentTiemLabel.text = [NSString stringWithFormat:@"%02ld:%02ld", (NSInteger)self.audioPlayer.currentTime / 60, (NSInteger)self.audioPlayer.currentTime % 60];
// 计算剩余时长
NSInteger surplus = self.audioPlayer.duration - self.audioPlayer.currentTime;
// 显示剩余时间
self.timeLabel.text = [NSString stringWithFormat:@"%02ld:%02ld", (NSInteger)surplus / 60, (NSInteger)surplus % 60];
// 让滑动条和音乐的播放进度关联
self.timeSlider.value = self.audioPlayer.currentTime;
// 如果 slider的 value和 audioPlayer 的 duration 相等则直接进入下一首歌
if (self.timeSlider.value >= self.audioPlayer.duration) {
[self nextMusic];
}
}
// 切到下一首
//- (void)nextMusic {
// 如果当前播放的音乐是播放列表中的最后一首
if (self.musicIndex == [[MusicHandle defaultHandle] musicCount] - 1) {
// 则切回第一首
self.musicIndex = 0;
} else {
// 否则播放下一首
self.musicIndex += 1;
}
// 获取到一个需要播放的 model
MusicModel *model = [[MusicHandle defaultHandle] modelWithIndex:self.musicIndex];
// 音频的地址
NSString *pathString = [[NSBundle mainBundle] pathForResource:model.musicName ofType:model.musicType];
// 音频的 data
NSData *data = [NSData dataWithContentsOfFile:pathString];
// 根据音频的 data 创建一个 AVAudioPlayer对象
self.audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:nil];
// 播放
[self.audioPlayer play];
}
// 切到上一首
//- (void)lastMusic {
// 如果当前播放的音乐是第一首
if (self.musicIndex == 0) {
// 则播放音乐列表中的最后一首
self.musicIndex = [[MusicHandle defaultHandle] musicCount] - 1;
} else {
// 否则播放当前音乐的前一曲
self.musicIndex -= 1;
}
// 获取到一个需要播放的 model
MusicModel *model = [[MusicHandle defaultHandle] modelWithIndex:self.musicIndex];
// 音频的地址
NSString *pathString = [[NSBundle mainBundle] pathForResource:model.musicName ofType:model.musicType];
// 音频的 URL
// NSURL *url = [NSURL URLWithString:pathString];
// 音频的 data
NSData *data = [NSData dataWithContentsOfFile:pathString];
// 根据音频的 data 创建一个 AVAudioPlayer对象
self.audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:nil];

// 播放
[self.audioPlayer play];

}
//- (IBAction)lastButtonClicked:(id)sender {
[self lastMusic];
}
//- (IBAction)playButtonClicked:(UIButton *)sender {
if (!_isPlay) {
// 让播放器播放音乐
[self.audioPlayer play];
// 记录播放状态
self.isPlay = YES;
// 改变 button 上的图片
[sender setImage:[UIImage imageNamed:@"pause"] forState:(UIControlStateNormal)];
// 播放的时候才创建 NSTimer
// NSTimer
// 第一个参数 : timer执行的时间
// 第二个参数 : target
// 第三个参数 : 方法选择
// 第四个参数 : 传递的值
// 第五个参数 : 是否重复
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timeChange) userInfo:nil repeats:YES];
// 启动计时器
[self.timer fire];
} else {
// 让音乐暂停
[self.audioPlayer pause];
// 改变播放状态
self.isPlay = NO;
// 改变 button 的图片
[sender setImage:[UIImage imageNamed:@"play"] forState:(UIControlStateNormal)];
// 移除 timer
[self.timer invalidate];
self.timer = nil;
}
}
//- (IBAction)nextButtonClicked:(id)sender {
[self nextMusic];
}
//- (IBAction)volumnSliderChange:(id)sender {
UISlider *slider = (UISlider *)sender;
// 用滑动条来控制当前播放器的音量
self.audioPlayer.volume = slider.value;
}
//- (IBAction)timeSliderChange:(UISlider *)sender {
UISlider *slider = (UISlider *)sender;
// 用滑动条来控制播放的进度
self.audioPlayer.currentTime = slider.value;
}
//- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 100;
}
//- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell_id" forIndexPath:indexPath];
return cell;
}
//- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
`

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349

推荐阅读更多精彩内容