标签:
一个小Demo
功能实现:列表页面和播放页面
知识点:歌词拆分 --- 把一首歌词拆分 --- 每一句拆分为一个模型 --- 所有的模型放到数组中 --- 工具类(单例)--- 私有属性
// 歌词拆分
-(void)lyricArrayWith:(BCCMusic *)model
{
// 数组清零
[self.allDataArray removeAllObjects];
NSString *lyricStr = model.lyric;
// 每行歌词
NSArray *array = [lyricStr componentsSeparatedByString:@"\n"];
for (NSString *str in array) {
NSArray *timeAndStrArray = [str componentsSeparatedByString:@"]"];
if ([timeAndStrArray.firstObject length] < 1) {
break;
}
NSString *timeStr = [timeAndStrArray.firstObject substringFromIndex:1];
NSString *minutes = [timeStr componentsSeparatedByString:@":"].firstObject;
NSString *seconds = [timeStr componentsSeparatedByString:@":"].lastObject;
// 时间
NSTimeInterval time = [minutes floatValue]*60 + [seconds floatValue];
// 歌词
NSString *smallLyricStr = [timeAndStrArray lastObject];
// 模型
BCCLyric *smallLyric = [BCCLyric lyricWithStr:smallLyricStr time:time];
[self.allDataArray addObject:smallLyric];
}
}
***工具类的作用:通过工具类的实例对象或者工具类 对应的方法 --- 达到相应的效果(目的)
***播放管理工具类
@class BCCPlayerTools;
@protocol BCCPlayerToolsDelegate <NSObject>
#pragma mark -声明代理方法
- (void)musicPlayingEndToTimeAction;
- (void)player:(BCCPlayerTools *)playTool playingWithProgress:(NSTimeInterval)progress;
@end
@interface BCCPlayerTools : NSObject
@property(nonatomic,assign)BOOL isPlaying;
@property(nonatomic,assign)NSInteger volume;
@property(nonatomic,assign)id<BCCPlayerToolsDelegate> delegate;
+ (instancetype)shareBCCPlayerTools;
#pragma mark -方法声明
// 准备
- (void)preparePlayingWith:(NSString *)mp3UrlString;
// 播放
- (void)play;
// 暂停
- (void)pause;
// 根据指定时间播放
- (void)seekToTime:(NSTimeInterval)time;
@end
#import "BCCPlayerTools.h"
#import <AVFoundation/AVFoundation.h>
@interface BCCPlayerTools ()
//
//{
// BOOL _isPrepare;
// BOOL _isPlaying;
//}
@property(nonatomic,strong)AVPlayer *player;
@property(nonatomic,strong)NSTimer *timer;
@end
@implementation BCCPlayerTools
+ (instancetype)shareBCCPlayerTools
{
static BCCPlayerTools *playerTool = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
playerTool = [[BCCPlayerTools alloc] init];
});
return playerTool;
}
- (instancetype)init
{
self = [super init];
if (self) {
// 初始化播放器
self.player = [[AVPlayer alloc] init];
// 添加通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playingToEndAction:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
}
return self;
}
#pragma mark -通知响应的方法
- (void)playingToEndAction:(NSNotification *)sender
{
if (self.delegate && [self.delegate respondsToSelector:@selector(musicPlayingEndToTimeAction)]) {
[self.delegate musicPlayingEndToTimeAction];
}
}
#pragma mark -方法声明
// 准备
- (void)preparePlayingWith:(NSString *)mp3UrlString
{
if (self.player.currentItem) {
// 移除
[self.player removeObserver:self forKeyPath:@"status"];
}
AVPlayerItem *item = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:mp3UrlString]];
[self.player replaceCurrentItemWithPlayerItem:item];
// [self.player play];
// KVO
[self.player addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"status"]) {
if (self.player.status == AVPlayerStatusReadyToPlay) {
[self play];
}
}
}
// 播放
- (void)play
{
// 先暂停
[self pause];
_isPlaying = YES;
[self.player play];
if (self.timer) {
return;
}
// 启动定时器
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(timerResponseAction:) userInfo:nil repeats:YES];
}
// 暂停
- (void)pause
{
if (!_isPlaying) {
return;
}
[self.player pause];
_isPlaying = NO; // 状态置NO
// 暂停后把定时器取消并置空
[self.timer invalidate];
self.timer = nil;
}
// 根据指定时间播放
- (void)seekToTime:(NSTimeInterval)time
{
// 先暂停
[self pause];
[self.player seekToTime:CMTimeMakeWithSeconds(time, self.player.currentTime.timescale) completionHandler:^(BOOL finished) {
if (finished) {
[self play];
}
}];
}
// 定时器响应方法
- (void)timerResponseAction:(NSTimer *)sender
{
if (self.delegate && [self.delegate respondsToSelector:@selector(player:playingWithProgress:)]) {
// 把当前播放器时间传出去
CGFloat progress = self.player.currentTime.value / self.player.currentTime.timescale;
[self.delegate player:self playingWithProgress:progress];
}
}
// 重写volume的setter方法
- (void)setVolume:(NSInteger)volume
{
self.player.volume = (CGFloat)volume;
}
- (BOOL)isPlaying
{
return _isPlaying;
}
@end
*** 音乐管理工具类
typedef void (^RefreshBlock) ();
@class BCCMusic;
@interface BCCMusicTools : NSObject
@property(nonatomic,assign,readonly)NSInteger count;
@property(nonatomic,copy)RefreshBlock block;
+ (instancetype)shareMusicToos;
// 获取对应的模型
- (BCCMusic *)musicWithIndex:(NSInteger)index;
@end
#import "BCCMusicTools.h"
#import "BCCMusic.h"
#import "BCCURLs.h"
@interface BCCMusicTools ()
@property(nonatomic,strong)NSMutableArray *musicListArray;
@end
@implementation BCCMusicTools
+ (instancetype)shareMusicToos
{
static BCCMusicTools *musicTool;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
musicTool = [[BCCMusicTools alloc] init];
[musicTool urlRequest];
});
return musicTool;
}
- (void)urlRequest
{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// 耗时操作
NSArray *array = [NSArray arrayWithContentsOfURL:[NSURL URLWithString:kMusicListURL]];
for (NSDictionary *dict in array) {
BCCMusic *model = [[BCCMusic alloc] init];
[model setValuesForKeysWithDictionary:dict];
[self.musicListArray addObject:model];
}
dispatch_async(dispatch_get_main_queue(), ^{
// 调用block --- 以后回调
self.block();
});
});
}
// 获取对应的模型
- (BCCMusic *)musicWithIndex:(NSInteger)index
{
return self.musicListArray[index];
}
// 懒加载
- (NSMutableArray *)musicListArray
{
if (!_musicListArray) {
_musicListArray = [NSMutableArray new];
}
return _musicListArray;
}
// 重写getter方法
- (NSInteger)count
{
return self.musicListArray.count;
}
@end
***歌词管理工具类
@class BCCMusic;
@interface BCCLyricTools : NSObject
@property(nonatomic,assign)NSInteger count;
+ (instancetype)shareBCCLyricTools;
#pragma mark -声明方法
// 歌词拆分
- (void)lyricArrayWith:(BCCMusic *)model;
// 根据下标 --- 拿到歌词
- (NSString *)stringWithIndex:(NSInteger)index;
// 通过时间 --- 拿到下标
- (NSInteger)indexWithTime:(NSTimeInterval)time;
@end
#import "BCCLyricTools.h"
#import "BCCMusic.h"
#import "BCCLyric.h"
@interface BCCLyricTools ()
#pragma mark -私有属性
@property(nonatomic,strong)NSMutableArray *allDataArray;
@end
@implementation BCCLyricTools
+ (instancetype)shareBCCLyricTools
{
static BCCLyricTools *lyricTool = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
lyricTool = [[BCCLyricTools alloc] init];
});
return lyricTool;
}
#pragma mark -声明方法
// 歌词拆分
-(void)lyricArrayWith:(BCCMusic *)model
{
// 数组清零
[self.allDataArray removeAllObjects];
NSString *lyricStr = model.lyric;
// 每行歌词
NSArray *array = [lyricStr componentsSeparatedByString:@"\n"];
for (NSString *str in array) {
NSArray *timeAndStrArray = [str componentsSeparatedByString:@"]"];
if ([timeAndStrArray.firstObject length] < 1) {
break;
}
NSString *timeStr = [timeAndStrArray.firstObject substringFromIndex:1];
NSString *minutes = [timeStr componentsSeparatedByString:@":"].firstObject;
NSString *seconds = [timeStr componentsSeparatedByString:@":"].lastObject;
// 时间
NSTimeInterval time = [minutes floatValue]*60 + [seconds floatValue];
// 歌词
NSString *smallLyricStr = [timeAndStrArray lastObject];
// 模型
BCCLyric *smallLyric = [BCCLyric lyricWithStr:smallLyricStr time:time];
[self.allDataArray addObject:smallLyric];
}
}
// 根据下标 --- 拿到歌词
- (NSString *)stringWithIndex:(NSInteger)index
{
BCCLyric *model = self.allDataArray[index];
return model.str;
}
// 通过时间 --- 拿到下标
- (NSInteger)indexWithTime:(NSTimeInterval)time
{
for (int i = 0;i < self.allDataArray.count;i++) {
BCCLyric *model = self.allDataArray[i];
if (time < model.time) {
return (i -1)>0?(i-1):0;
}
}
return 0;
}
// 重写getter方法
- (NSInteger)count
{
return self.allDataArray.count;
}
// 懒加载
- (NSMutableArray *)allDataArray
{
if (!_allDataArray) {
_allDataArray = [NSMutableArray array];
}
return _allDataArray;
}
@end
***播放详情页面Controller
@interface BCCMusicPlayingViewController : UIViewController
@property(nonatomic,assign)NSInteger index;
+ (instancetype)shareBCCMusicPlayingViewController;
@end
#import "BCCMusicPlayingViewController.h"
#import "BCCPlayerTools.h"
#import "BCCMusicTools.h"
#import "BCCMusic.h"
#import "BCCLyricTools.h"
#import "UIImageView+WebCache.h"
@interface BCCMusicPlayingViewController ()<BCCPlayerToolsDelegate,UITableViewDataSource,UITableViewDelegate>
{
// 当前正在播放的下标
NSInteger _currentIndex;
}
@property (strong, nonatomic) IBOutlet UILabel *musicNameLabel;
@property (strong, nonatomic) IBOutlet UILabel *musicSingerLabel;
@property (strong, nonatomic) IBOutlet UIImageView *musicImageView;
@property (strong, nonatomic) IBOutlet UISlider *timeSlider;
@property (strong, nonatomic) IBOutlet UISlider *volumeSlider;
@property (strong, nonatomic) IBOutlet UILabel *currentTimeLabel;
@property (strong, nonatomic) IBOutlet UILabel *allTimeLabel;
@property (strong, nonatomic) IBOutlet UITableView *lyricTableView;
@property (strong, nonatomic) IBOutlet UIButton *stopAndStartButton;
- (IBAction)timeSliderAction:(UISlider *)sender;
- (IBAction)volumeSliderActon:(UISlider *)sender;
@end
@implementation BCCMusicPlayingViewController
+ (instancetype)shareBCCMusicPlayingViewController
{
static BCCMusicPlayingViewController *musicPlayingVC;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
musicPlayingVC = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"BCCMusicPlayingViewController"];
});
return musicPlayingVC;
}
- (void)viewDidLoad {
[super viewDidLoad];
_currentIndex = -1;
// 设置代理
[BCCPlayerTools shareBCCPlayerTools].delegate = self;
self.lyricTableView.dataSource = self;
self.lyricTableView.delegate = self;
// 注册cell
[self.lyricTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"lyricCell"];
self.lyricTableView.separatorStyle = NO;
// 声音slider
self.volumeSlider.maximumValue = 100;
// 声音默认为2
self.volumeSlider.value = 2.0;
// 设置圆形图片
self.musicImageView.layer.masksToBounds = YES;
self.musicImageView.layer.cornerRadius = 125;
[self.timeSlider setThumbImage:[UIImage imageNamed:@"thumb"] forState:UIControlStateNormal];
[self.volumeSlider setThumbImage:[UIImage imageNamed:@"thumb"] forState:UIControlStateNormal];
}
-(void)viewWillAppear:(BOOL)animated
{
// 开始播放
[self startPlaying];
}
#pragma mark - 开始播放
- (void)startPlaying
{
if (_currentIndex == _index) {
return;
}
_currentIndex = _index;
[self playingWithIndex:_currentIndex];
}
#pragma mark 根据下标播放
- (void)playingWithIndex:(NSInteger)index
{
// 先暂停 --- 重要
[[BCCPlayerTools shareBCCPlayerTools] pause];
BCCMusic *music = [[BCCMusicTools shareMusicToos] musicWithIndex:index];
[[BCCPlayerTools shareBCCPlayerTools] preparePlayingWith:music.mp3Url];
// 总时间
self.allTimeLabel.text = [self returnStringWithTime:[music.duration doubleValue]/1000];
self.timeSlider.maximumValue = [music.duration doubleValue]/1000;
// 工具拆分歌词
[[BCCLyricTools shareBCCLyricTools] lyricArrayWith:music];
[self.lyricTableView reloadData];
// 更新
self.musicNameLabel.text = music.name;
self.musicSingerLabel.text = music.singer;
[self.musicImageView sd_setImageWithURL:[NSURL URLWithString:music.picUrl] placeholderImage:[UIImage imageNamed:@"01.jpg"]];
// button默认图片
[self.stopAndStartButton setBackgroundImage:[UIImage imageNamed:@"pause.png"] forState:UIControlStateNormal];
[self stopAndStartButtonDidClicked:nil];
}
#pragma mark -BCCPlayerToolsDelegate代理方法
// 代理方法 --- BCCPlayerToolsDelegate --- 自动下一首
-(void)musicPlayingEndToTimeAction
{
[self nextMusicButtonDidClicked:nil];
}
-(void)player:(BCCPlayerTools *)playTool playingWithProgress:(NSTimeInterval)progress
{
// 动画 --- 旋转
self.musicImageView.transform = CGAffineTransformRotate(_musicImageView.transform, M_PI / 180);
// 一直被执行的代理方法(定时器)
// 当前时间
self.currentTimeLabel.text = [self returnStringWithTime:progress];
self.timeSlider.value = progress;
NSInteger index = [[BCCLyricTools shareBCCLyricTools] indexWithTime:progress];
[self.lyricTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] animated:YES scrollPosition:UITableViewScrollPositionMiddle];
}
#pragma mark -秒数转00:00格式的字符串
- (NSString *)returnStringWithTime:(NSTimeInterval)time
{
NSInteger minutes = time/60;
NSInteger seconds = (NSInteger)time%60;
NSString *str = [NSString stringWithFormat:@"%02ld:%02ld",(long)minutes,(long)seconds];
return str;
}
#pragma mark -stroyboard关联事件
// 上一首
- (IBAction)beforeMusicButtonDidClicked:(UIButton *)sender {
_currentIndex --;
if (_currentIndex < 0) {
_currentIndex = [BCCMusicTools shareMusicToos].count - 1;
}
_index = _currentIndex;
[self playingWithIndex:_currentIndex];
}
// 下一首
- (IBAction)nextMusicButtonDidClicked:(UIButton *)sender {
_currentIndex ++;
if (_currentIndex > [BCCMusicTools shareMusicToos].count - 1) {
_currentIndex = 0;
}
_index = _currentIndex;
[self playingWithIndex:_currentIndex];
}
// 暂停-开始
- (IBAction)stopAndStartButtonDidClicked:(UIButton *)sender {
NSLog(@"%d",[BCCPlayerTools shareBCCPlayerTools].isPlaying);
if ([BCCPlayerTools shareBCCPlayerTools].isPlaying) {
[[BCCPlayerTools shareBCCPlayerTools] pause];
[self.stopAndStartButton setBackgroundImage:[UIImage imageNamed:@"play.png"] forState:UIControlStateNormal];
}else{
[[BCCPlayerTools shareBCCPlayerTools] play];
[self.stopAndStartButton setBackgroundImage:[UIImage imageNamed:@"pause.png"] forState:UIControlStateNormal];
}
}
- (IBAction)cancelButtonDidClicked:(UIButton *)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
// 时间滑竿
- (IBAction)timeSliderAction:(UISlider *)sender {
// 根据slider的value播放 --- 指定位置播放
[[BCCPlayerTools shareBCCPlayerTools] seekToTime:sender.value];
}
// 声音滑竿
- (IBAction)volumeSliderActon:(UISlider *)sender {
[BCCPlayerTools shareBCCPlayerTools].volume = sender.value;
}
/*******************************lyricTableView的代理方法***********************************/
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [BCCLyricTools shareBCCLyricTools].count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"lyricCell" forIndexPath:indexPath];
cell.textLabel.text = [[BCCLyricTools shareBCCLyricTools] stringWithIndex:indexPath.row];
// 文字居中
cell.textLabel.textAlignment = NSTextAlignmentCenter;
cell.textLabel.highlightedTextColor = [UIColor redColor];
cell.selectedBackgroundView = ({
UIView *view = [[UIView alloc] initWithFrame:cell.frame];
view.backgroundColor = [UIColor clearColor];
view;
});
return cell;
}
@end
***列表展示页面
@interface BCCMusicListTableViewController : UITableViewController
@end
#import "BCCMusicListTableViewController.h"
#import "BCCMusicListTableViewCell.h"
#import "BCCMusicTools.h"
#import "BCCMusicPlayingViewController.h"
#import "MBProgressHUD.h"
@interface BCCMusicListTableViewController ()<UITableViewDataSource,UITableViewDelegate>
@end
@implementation BCCMusicListTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
// tableview注册cell
[self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([BCCMusicListTableViewCell class]) bundle:nil] forCellReuseIdentifier:@"BCCMusicListTableViewCell"];
self.tableView.dataSource = self;
self.tableView.delegate = self;
[BCCMusicTools shareMusicToos].block = ^(){
[self.tableView reloadData];
};
[self hudload];
}
#pragma mark -小菊花加载
- (void)hudload
{
MBProgressHUD *hud = [[MBProgressHUD alloc] initWithFrame:self.view.frame];
[self.view addSubview:hud];
hud.dimBackground = YES;
hud.labelText = @"加载中...";
[hud showWhileExecuting:@selector(hudSleep) onTarget:self withObject:nil animated:YES];
}
- (void)hudSleep
{
sleep(2);
}
#pragma mark - TableView代理方法
// 行数rows
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// NSLog(@"%ld",[BCCMusicTools shareMusicToos].count);
return [BCCMusicTools shareMusicToos].count;
}
// cell设置
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
BCCMusicListTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BCCMusicListTableViewCell" forIndexPath:indexPath];
BCCMusic *model = [[BCCMusicTools shareMusicToos] musicWithIndex:indexPath.row];
[cell initWithMusic:model];
// NSLog(@"%@",model.lyric);
return cell;
}
// 行高
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 100;
}
// cell点击事件
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// 取消选中状态 --- UITableViewController --- 自动取消选中状态
BCCMusicPlayingViewController *musicPlayingVC = [BCCMusicPlayingViewController shareBCCMusicPlayingViewController];
// 传值
musicPlayingVC.index = indexPath.row;
[self showDetailViewController:musicPlayingVC sender:nil];
}
// BarButtonItem关联事件
- (IBAction)rightBarButtonDidClicked:(UIBarButtonItem *)sender {
BCCMusicPlayingViewController *musicPlayingVC = [BCCMusicPlayingViewController shareBCCMusicPlayingViewController];
[self showDetailViewController:musicPlayingVC sender:nil];
}
@end
标签:
原文地址:http://www.cnblogs.com/bachl/p/4716734.html