本地音樂播放器的使用

音樂播放器的簡單使用:
<1>AVAudioPlayer使用簡單方便,但只能播放本地音頻,不支持網絡連接的播放.
<2>AVPlayer可以播放本地音頻也支持網絡播放以及視屏播放,但是提供接口較少,處理音頻不夠靈活.
使用它們都需要導入系統(tǒng)的AVFoundation框架
今天介紹一下AVAudioPlayer的使用

它的使用非常簡單直接獲取本地音樂路徑
NSString *path = [[NSBundle mainBundle] pathForResource:@"本地音樂的名字" ofType:@"后綴"];
NSURL *url = [NSURL fileURLWithPath:path];
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[player play];
這樣就可以播放了

但是如果添加上暫停 上一曲 下一曲 歌詞 功能 就不能這么簡單了由于代碼有點多直接上代碼了 每一次播放都會創(chuàng)建新的player, 再把上一次的清掉, 并且, 承載音樂播放的VC也不能多次創(chuàng)建

先創(chuàng)建一個Model對象存放本地音樂的數據
Model.h

#import <Foundation/Foundation.h>
@interface ModelOfMusic : NSObject
@property (nonatomic, copy) NSString *filename;
@property (nonatomic, copy) NSString *icon;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *singer;
@property (nonatomic, copy) NSString *singerIcon;
@property (nonatomic, copy) NSString *lrcname;
- (instancetype)initWithDic:(NSDictionary *)dic;
+ (ModelOfMusic *)modelWithDic:(NSDictionary *)dic;
@end

Model.m

#import "ModelOfMusic.h"
@implementation ModelOfMusic
- (instancetype)initWithDic:(NSDictionary *)dic {

    self = [super init];
    if (self) {
        
        [self setValuesForKeysWithDictionary:dic];
    }
    return self;
}
+ (ModelOfMusic *)modelWithDic:(NSDictionary *)dic {

    return [[self alloc] initWithDic:dic];
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {   
}
- (id)valueForUndefinedKey:(NSString *)key {

    return nil;
}
@end

還要創(chuàng)建管理音樂數據的類

#import <Foundation/Foundation.h>
@class ModelOfMusic;
@interface WHMusicTool : NSObject
/** 返回所有的歌曲 */
+ (NSArray *)arrayOfMusics;
/** 返回正在播放的歌曲 */
+ (ModelOfMusic *)playingMusic;
+ (void)setPlayingMusic:(ModelOfMusic *)playingMusic;
/** 下一首歌曲 */
+ (ModelOfMusic *)nextMusic;
/** 上一首歌曲 */
+ (ModelOfMusic *)lastMusic;
@end
#import "WHMusicTool.h"
#import "ModelOfMusic.h"
static NSArray *_arrayOfMusics;
static ModelOfMusic *_playingMusic;

@implementation WHMusicTool

#pragma mark ------------  返回所有的歌曲  -----------
+ (NSArray *)arrayOfMusics {

    if (_arrayOfMusics.count == 0) {
        NSMutableArray *mArr = [NSMutableArray array];
        
        NSString *path = [[NSBundle mainBundle] pathForResource:@"Musics" ofType:@"plist"];
        NSArray *array = [NSArray arrayWithContentsOfFile:path];
        for (NSDictionary *dic in array) {
            
            ModelOfMusic *model = [ModelOfMusic modelWithDic:dic];
            [mArr addObject:model];
        }
        _arrayOfMusics = mArr;
    }
    return _arrayOfMusics;
}
+ (void)setPlayingMusic:(ModelOfMusic *)playingMusic {

    /** 
     * 如果沒有傳入需要播放的歌曲, 或者是傳入歌曲名不在音樂庫中, 那么就直接返回
     * 如果需要播放的歌曲就是當前正在播放的歌曲, 那么就直接返回
     */
    if (!playingMusic || ![[self arrayOfMusics] containsObject:playingMusic]) {
        
        return;
    }
    if (_playingMusic == playingMusic) {
        
        return;
    }
    _playingMusic = playingMusic;
}
#pragma mark ------------  返回正在播放的歌曲  -----------
+ (ModelOfMusic *)playingMusic {

    return _playingMusic;
}
#pragma mark ------------  下一曲  -----------
+ (ModelOfMusic *)nextMusic {

    // 設定一個初值
    NSInteger nextIndex = 0;
    if (_playingMusic) {
        
        // 獲取當前播放音樂的索引
        NSInteger playingIndex = [[self arrayOfMusics] indexOfObject:_playingMusic];
        // 設置下一首音樂的索引
        nextIndex = playingIndex + 1;
        if (nextIndex >= [self arrayOfMusics].count) {
            nextIndex = 0;
        }
    }
    return [self arrayOfMusics][nextIndex];
}
#pragma mark ------------  上一曲  -----------
+ (ModelOfMusic *)lastMusic {

    // 設定一個初值
    NSInteger lastIndex = 0;
    if (_playingMusic) {
        
        // 獲取當前播放音樂的索引
        NSInteger playingIndex = [[self arrayOfMusics] indexOfObject:_playingMusic];
        // 設置下一曲的索引
        lastIndex = playingIndex - 1;
        if (lastIndex < 0) {
            
            lastIndex = [self arrayOfMusics].count - 1;
        }
    }
    return [self arrayOfMusics][lastIndex];
}
@end

管理音樂播放器的類

#import <Foundation/Foundation.h>
@class AVAudioPlayer;
@interface WHAudioTool : NSObject
/** 播放音樂文件 */
+ (AVAudioPlayer *)playMusic:(NSString *)fileName;
/** 暫停播放 */
+ (void)pauseMusic:(NSString *)fileName;
/** 播放音樂 */
+ (void)stopMusic:(NSString *)fileName;
/** 播放音效文件 */
+ (void)playSound:(NSString *)fileName;
/** 銷毀音效 */
+ (void)disposeSound:(NSString *)fileName;
@end
#import "WHAudioTool.h"
#import <AVFoundation/AVFoundation.h>
@implementation WHAudioTool
static NSMutableDictionary *_musicPlayers;
static NSMutableDictionary *_soundIDs;
#pragma mark ------------  存放所有的音樂播放器  -----------
+ (NSMutableDictionary *)musicPalyers {

    if (_musicPlayers == nil) {
        
        _musicPlayers = [NSMutableDictionary dictionary];
    }
    return _musicPlayers;
}
#pragma mark ------------  存放所有的音效ID  -----------
+ (NSMutableDictionary *)soundIDs {

    if (_soundIDs == nil) {
        
        _soundIDs = [NSMutableDictionary dictionary];
    }
    return _soundIDs;
}
#pragma mark ------------  播放音樂  -----------
+ (AVAudioPlayer *)playMusic:(NSString *)fileName {

    // 如果沒有傳入文件名, 直接返回
    if (!fileName) {
        
        return nil;
    }
    // 1.取出對應的播放器
    AVAudioPlayer *player = [[self musicPalyers] objectForKey:fileName];
    // 2.如果沒有播放器, 就進行初始化
    if (!player) {
        
        // 2.1 音頻文件的URL
        NSURL *url = [[NSBundle mainBundle] URLForResource:fileName withExtension:nil];
        //      如果url為空, 直接返回
        if (!url) {
            return nil;
        }
        // 2.2創(chuàng)建播放器
        player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
        // 2.3 緩沖
        //      如果緩沖失敗 直接返回
        if (![player prepareToPlay]) {
            
            return nil;
        }
        // 2.4存入字典
//        [self musicPalyers][fileName] = player;
        [[self musicPalyers] setObject:player forKey:fileName];
    }
    // 3.播放
    if (![player isPlaying]) {
        
        // 如果當前沒處于播放狀態(tài), 那么就播放
        [player play];
        return player;
    }
    
    // 正在播放, 那么就返回YES
    return player;
}
#pragma mark ------------  暫停  -----------
+ (void)pauseMusic:(NSString *)fileName {

    // 如果沒有傳入文件名, 那么就直接返回
    if (!fileName) {
        
        return;
    }    
    // 1. 取出對應的播放器
    AVAudioPlayer *player = [[self musicPalyers] objectForKey:fileName];
    
    // 2. 暫停(如果player為空, 那相當于[nil pause]不用做處理)
    [player pause];
}
#pragma mark ------------  stop  -----------
+ (void)stopMusic:(NSString *)fileName {

    // 如果沒有傳入文件名, 直接返回
    if (!fileName) {
        
        return;
    }
    // 1. 取出對應的播放器
    AVAudioPlayer *player = [[self musicPalyers] objectForKey:fileName];
    // 2.停止
    [player stop];
    // 3.將播放器從字典中移除
    [[self musicPalyers] removeObjectForKey:fileName];   
}
#pragma mark ------------  播放音效  -----------
+ (void)playSound:(NSString *)fileName {

    if (!fileName) {
        
        return;
    }
    // 1. 取出對應的音效
    SystemSoundID soundID = (SystemSoundID)[[self soundIDs] objectForKey:fileName];
    
    // 2. 播放音效
    // 2.1 如果音效ID不存在, 那么就創(chuàng)建
    if (!soundID) {
        
        // 音效文件的URL
        NSURL *url = [[NSBundle mainBundle] URLForResource:fileName withExtension:nil];
        //      如果url不存在, 直接返回
        if (!url) {
            
            return;
        }
        OSStatus status = AudioServicesCreateSystemSoundID((__bridge CFURLRef)(url), &soundID);
        [[self soundIDs] setObject:@(soundID) forKey:fileName];
    }
    // 2.2 有音效ID后, 播放音效
    AudioServicesPlaySystemSound(soundID);
}
#pragma mark ------------  銷毀音效  -----------
+ (void)disposeSound:(NSString *)fileName {

    // 如果傳入的文件名為空, 直接返回
    if (!fileName) {
        return;
    }
    // 1. 取出對應的音效
    SystemSoundID soundID = (SystemSoundID)[[self soundIDs] objectForKey:fileName];
    // 2. 銷毀
    if (soundID) {
        AudioServicesDisposeSystemSoundID(soundID);   
        // 2.1 銷毀后, 從字典中移除
        [[self soundIDs] removeObjectForKey:fileName];
    }   
}
@end

解析歌詞的類

#import <Foundation/Foundation.h>
@interface LrcParser : NSObject
@property (nonatomic, retain) NSMutableArray *timerArray;
@property (nonatomic, retain) NSMutableArray *wordArray;
-(void)parserLrc:(NSString *)name type:(NSString *)type;
@end
#import "LrcParser.h"
@implementation LrcParser
- (instancetype)init{
    self = [super init];
    if (self) {
        self.timerArray = [[NSMutableArray alloc] init];
        self.wordArray = [[NSMutableArray alloc] init];
        
    }
    return self;
}
-(void)parserLrc:(NSString *)name type:(NSString *)type{
    
    NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:type];
    NSURL *url = [NSURL fileURLWithPath:path];
    //轉換 C 字符串
    NSString *lrc = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
    
    if (![lrc isEqual:nil]) {
        NSArray *sepArray = [lrc componentsSeparatedByString:@"["];
        NSArray *lineArray = [[NSArray alloc] init];
        for (int i = 0; i < sepArray.count; i++) {
            if ([sepArray[i] length] > 0) {
                lineArray = [sepArray[i] componentsSeparatedByString:@"]"];
                if (![lineArray[0] isEqualToString:@"\n"]) {
                    [self.timerArray addObject:lineArray[0]];
                    [self.wordArray addObject:lineArray.count > 1 ? lineArray[1] : @""];
                }
            }
        }
    }   
}
@end

給創(chuàng)建View的frame寫的類目(這個可以不要)

#import <UIKit/UIKit.h>
@interface UIView (Frame)
@property (nonatomic, assign) CGFloat wh_x;
@property (nonatomic, assign) CGFloat wh_y;
@property (nonatomic, assign) CGFloat wh_width;
@property (nonatomic, assign) CGFloat wh_height;

@property (nonatomic, assign) CGFloat wh_centerX;
@property (nonatomic, assign) CGFloat wh_centerY;
@end
#import "UIView+Frame.h"

@implementation UIView (Frame)

// 原點的x
// set方法
- (void)setWh_x:(CGFloat)wh_x {

    CGRect rect = self.frame;
    rect.origin.x = wh_x;
    self.frame = rect;
}
// get方法
- (CGFloat)wh_x {

    return self.frame.origin.x;
}

// 原點的y
// set方法
- (void)setWh_y:(CGFloat)wh_y {

    CGRect rect = self.frame;
    rect.origin.y = wh_y;
    self.frame = rect;
}
// get方法
- (CGFloat)wh_y {

    return self.frame.origin.y;
}
// view的width
// set方法
- (void)setWh_width:(CGFloat)wh_width {

    CGRect rect = self.frame;
    rect.size.width = wh_width;
    self.frame = rect;
}
// get方法
- (CGFloat)wh_width {

    return self.frame.size.width;
}
// view的height
// set方法
- (void)setWh_height:(CGFloat)wh_height {

    CGRect rect = self.frame;
    rect.size.height = wh_height;
    self.frame = rect;
}
// get方法
- (CGFloat)wh_height {

    return self.frame.size.height;
}

/** 中心點 */
//X
// set方法
- (void)setWh_centerX:(CGFloat)wh_centerX {

    CGPoint center = self.center;
    center.x = wh_centerX;
    
    self.center = center;
}
// get方法
- (CGFloat)wh_centerX {

    return self.center.x;
}
//Y
// set方法
- (void)setWh_centerY:(CGFloat)wh_centerY {

    CGPoint center = self.center;
    center.y = wh_centerY;
    self.center = center;
}
// get方法
- (CGFloat)wh_centerY {

    return self.center.y;
}
@end

自定義的一個View

#import <UIKit/UIKit.h>
typedef void(^Play)(UIButton *play);
typedef void(^Pause)(UIButton *pause);
typedef void(^ButtonBlock)(UIButton *btn);
@interface PlayView : UIView
//- (void)play:(void (^)(UIButton *play))play
//       pause:(void (^)(UIButton *pause))pause;
- (void)play:(ButtonBlock)play pause:(ButtonBlock)pause last:(ButtonBlock)last next:(ButtonBlock)next;
@end
#import "PlayView.h"
#import "UIView+Frame.h"

@interface PlayView ()

@property (nonatomic, strong) UIButton *buttonOfPlay;

@property (nonatomic, strong) UIButton *buttonOfLast;

@property (nonatomic, strong) UIButton *buttonOfNext;

//@property (nonatomic, copy) void (^play)(UIButton *play);
@property (nonatomic, copy) ButtonBlock play;

//@property (nonatomic, copy) void (^pause)(UIButton *pause);
@property (nonatomic, copy) ButtonBlock pause;
@property (nonatomic, copy) ButtonBlock last;
@property (nonatomic, copy) ButtonBlock next;
@end
@implementation PlayView
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/
- (instancetype)initWithFrame:(CGRect)frame {

    self = [super initWithFrame:frame];
    if (self) {
        
        [self createSubViews];
    }
    return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {

    self = [super initWithCoder:aDecoder];
    if (self) {
        
        [self createSubViews];
    }
    return self;
}

- (void)createSubViews {

    _buttonOfLast = [self buttonImageWithName:@"player_btn_pre_normal" action:@selector(last:)];
   
    
    _buttonOfPlay = [self buttonImageWithName:@"player_btn_pause_normal" action:@selector(pause:)];
   
    
    _buttonOfNext = [self buttonImageWithName:@"player_btn_next_normal" action:@selector(next:)];
   
}
#pragma mark ------------  self的屬性block賦值 -----------
- (void)play:(ButtonBlock)play pause:(ButtonBlock)pause last:(ButtonBlock)last next:(ButtonBlock)next {
    
    self.play = play;
    self.pause = pause;
    self.last = last;
    self.next = next;
}
#pragma mark ------------  Last  -----------
- (void)last:(UIButton *)lastBtn {
    
    self.last(lastBtn);
    [_buttonOfPlay setImage:[UIImage imageNamed:@"player_btn_pause_normal"] forState:UIControlStateNormal];
    
}
#pragma mark ------------  Next  -----------
- (void)next:(UIButton *)nextBtn {

    self.next(nextBtn);
    [_buttonOfPlay setImage:[UIImage imageNamed:@"player_btn_pause_normal"] forState:UIControlStateNormal];
}
#pragma mark ------------  Play  -----------
- (void)play:(UIButton *)playBtn {

    [playBtn setImage:[UIImage imageNamed:@"player_btn_pause_normal"] forState:UIControlStateNormal];
    [playBtn removeTarget:self action:@selector(play:) forControlEvents:UIControlEventTouchUpInside];
    [playBtn addTarget:self action:@selector(pause:) forControlEvents:UIControlEventTouchUpInside];
    
    self.play(playBtn);
}
#pragma mark ------------  Pause  -----------
- (void)pause:(UIButton *)pauseBtn {

    [pauseBtn setImage:[UIImage imageNamed:@"player_btn_play_normal"] forState:UIControlStateNormal];
    [pauseBtn removeTarget:self action:@selector(pause:) forControlEvents:UIControlEventTouchUpInside];
    [pauseBtn addTarget:self action:@selector(play:) forControlEvents:UIControlEventTouchUpInside];
    
    self.pause(pauseBtn);
}
#pragma mark ------------  Layout布局  -----------
- (void)layoutSubviews {

    [super layoutSubviews];
    
    _buttonOfPlay.frame = CGRectMake(0, 0, CGRectGetHeight(self.bounds), CGRectGetHeight(self.bounds));
    _buttonOfPlay.center = CGPointMake(CGRectGetWidth(self.bounds) / 2, CGRectGetHeight(self.bounds) / 2);
    
    _buttonOfLast.frame = CGRectMake(0, 0, CGRectGetWidth(_buttonOfPlay.bounds) * 2 / 3, CGRectGetHeight(_buttonOfPlay.bounds) * 2 / 3);
    _buttonOfLast.wh_centerX = _buttonOfPlay.wh_centerX / 2;
    _buttonOfLast.wh_centerY = _buttonOfPlay.wh_centerY;
    
    _buttonOfNext.frame = CGRectMake(0, 0, CGRectGetWidth(_buttonOfPlay.bounds) * 2 / 3, CGRectGetHeight(_buttonOfPlay.bounds) * 2 / 3);
    _buttonOfNext.wh_centerX = _buttonOfPlay.wh_centerX * 1.5;
    _buttonOfNext.wh_centerY = _buttonOfPlay.wh_centerY;
}
#pragma mark ------------  創(chuàng)建Button的共同方法  -----------
- (UIButton *)buttonImageWithName:(NSString *)imageName action:(SEL)action {

    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
    [self addSubview:button];
    
    [button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
    return button;
}
@end

首頁的VC是一個tableView存放本地音樂列表.m

#import "ViewController.h"
#import "ModelOfMusic.h"
#import "VCOfPlayer.h"
#import "WHMusicTool.h"
@interface ViewController () <UITableViewDelegate, UITableViewDataSource>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSMutableArray *mArrOfMusic;
@property (nonatomic, strong) VCOfPlayer *vcOfPlayer;
@end
@implementation ViewController
-(VCOfPlayer *)vcOfPlayer {

    if (_vcOfPlayer == nil) {
        
        _vcOfPlayer = [[VCOfPlayer alloc] init];
    }
    return _vcOfPlayer;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self createTableView];
}
- (void)createTableView {

    self.tableView = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds style:UITableViewStylePlain];
    
    [self.view addSubview:_tableView];
    _tableView.delegate = self;
    _tableView.dataSource = self;
    
    [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"pool"];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return [WHMusicTool arrayOfMusics].count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"pool"];
    
    ModelOfMusic *model = [WHMusicTool arrayOfMusics][indexPath.row];
    cell.textLabel.text = model.name;
    return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    return 70;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    
    // 2.設置正在播放的歌曲
    [WHMusicTool setPlayingMusic:[WHMusicTool arrayOfMusics][indexPath.row]];
    
    // 調用show方法
    [self.vcOfPlayer show];
}
@end

顯示播放頁的VC.h

#import <UIKit/UIKit.h>
@interface VCOfPlayer : UIViewController
- (void)show;
@end

播放頁面的.m


#import "VCOfPlayer.h"
#import <AVFoundation/AVFoundation.h>
#import "PlayView.h"
#import "ModelOfMusic.h"
#import "UIView+Frame.h"
#import "WHMusicTool.h"
#import "WHAudioTool.h"
#import "LrcParser.h"

@interface VCOfPlayer () <UITableViewDelegate, UITableViewDataSource>
// 歌手的圖片
@property (nonatomic, strong) UIImageView *imageViewOfSinger;
// 歌名
@property (nonatomic, strong) UILabel *labelOfSongName;
// 歌手名
@property (nonatomic, strong) UILabel *labelOfSingerName;
// 音樂播放器
@property (nonatomic, strong) AVAudioPlayer *player;
// Model類
@property (nonatomic, strong) ModelOfMusic *playingMusic;
// 滑動指示器
@property (nonatomic, strong) UISlider *slider;
// 當前時間
@property (nonatomic, strong) UILabel *labelOfMin;
// 歌曲總時間
@property (nonatomic, strong) UILabel *labelOfMax;
// 時間
@property (nonatomic, strong) NSTimer *timer;
// 解析歌詞類
@property (nonatomic, strong) LrcParser *lrcContent;
// 歌詞的當前行
@property (nonatomic, assign) NSInteger currentRow;
// 顯示歌詞的tableView
@property (nonatomic, strong) UITableView *tableView;
@end
@implementation VCOfPlayer
- (void)show {

    // 1.禁用整個app的點擊事件
    UIWindow *window = [UIApplication sharedApplication].keyWindow;
    window.userInteractionEnabled = NO;
    
    // 2.添加播放界面
    //   設置View的大小覆蓋整個窗口
    self.view.frame = window.bounds;
    
    // 設置View顯示
    self.view.hidden = NO;
    // 把View添加到窗口上
    [window addSubview:self.view];
    
    // 3.檢測是否換了歌曲
    if (self.playingMusic != [WHMusicTool playingMusic]) {
        
        [self resetPlayMusic];
    }
    
    // 3.使用動畫讓View顯示
    self.view.wh_y = self.view.wh_height;
    [UIView animateWithDuration:0.25 animations:^{
       
        self.view.wh_y = 0;
    } completion:^(BOOL finished) {
        
        // 設置音樂數據
        [self startPlayingMusic];
        
        _imageViewOfSinger.backgroundColor = [UIColor brownColor];
        window.userInteractionEnabled = YES;
    }];
}

- (void)back {
    
    // 1.禁用整個app的點擊事件
    UIWindow *window = [UIApplication sharedApplication].keyWindow;
    
    window.userInteractionEnabled = NO;
    
    // 2.動畫隱藏View
    [UIView animateWithDuration:0.25 animations:^{
        
        self.view.wh_y = window.wh_height;
    } completion:^(BOOL finished) {
        
        window.userInteractionEnabled = YES;
        
        // 設置View的隱藏能節(jié)省一些性能
        self.view.hidden = YES;
    }];
}
#pragma mark ------------  重置正在播放得到音樂  -----------

- (void)resetPlayMusic {

    // 1. 重置界面數據
//    self.imageViewOfSinger.image = [UIImage imageNamed:@"28131977_1383101943208"];
//    self.labelOfSongName = nil;
//    self.labelOfSingerName = nil;
    
    // 2. 停止播放
    [WHAudioTool stopMusic:self.playingMusic.filename];
    
    // 把播放器進行清空
    self.player = nil;
}
#pragma mark ------------  開始播放音樂數據  -----------
- (void)startPlayingMusic {

    // 1. 設置界面數據
    // 取出當前正在播放的音樂
    
    
    // 如果當前播放的音樂就是傳入的音樂, 直接返回
    if (self.playingMusic == [WHMusicTool playingMusic]) {
        
        return;
    }
    //存取音樂
    self.playingMusic = [WHMusicTool playingMusic];
    self.imageViewOfSinger.image = [UIImage imageNamed:self.playingMusic.icon];
    self.labelOfSongName.text = self.playingMusic.name;
    self.labelOfSingerName.text = self.playingMusic.singer;
   
    // 2. 開始播放
    self.player = [WHAudioTool playMusic:self.playingMusic.filename];
    
    /** 設置進度條 */
    _slider.minimumValue = 0.0f;
    _slider.maximumValue = self.player.duration;
    [_slider addTarget:self action:@selector(sliderAction:) forControlEvents:UIControlEventValueChanged];
    
    
    /** 定時器(讓slider隨player播放移動) */
    self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(changeTime:) userInfo:nil repeats:YES];
    
    /** 進度條兩邊的時間 */
    NSInteger allTime = self.player.duration;
    if (allTime / 60 < 10) {
        
        _labelOfMax.text = [NSString stringWithFormat:@"0%ld:%ld", allTime / 60, allTime % 60];
    } else if (allTime / 60 > 10) {
    
        _labelOfMax.text = [NSString stringWithFormat:@"%ld:%ld", allTime / 60, allTime % 60];
    }
    
    [self createLyricTableView];
}

- (void)sliderAction:(UISlider *)slider {

    self.player.currentTime = self.slider.value;
    
}
/** 定時器 */
- (void)changeTime:(NSTimer *)timer {

    self.slider.value = self.player.currentTime;
    
    // 時間跟著走
    NSInteger currentTime = self.player.currentTime;
    if (currentTime / 60 < 10) {
        
        if (currentTime % 60 < 10) {
            
            _labelOfMin.text = [NSString stringWithFormat:@"0%ld:0%ld", currentTime / 60, currentTime % 60];
        } else if (currentTime % 60 > 10) {
        
            _labelOfMin.text = [NSString stringWithFormat:@"0%ld:%ld", currentTime / 60, currentTime % 60];
        }
    } else if (currentTime / 60 > 10) {
    
        if (currentTime % 60 < 10) {
            
            _labelOfMin.text = [NSString stringWithFormat:@"%ld:0%ld", currentTime / 60, currentTime % 60];
        } else if (currentTime % 60 > 10) {
        
            _labelOfMin.text = [NSString stringWithFormat:@"%ld:%ld", currentTime / 60, currentTime % 60];
        }
    } 
   
    for (int i = 0; i < self.lrcContent.timerArray.count; i++) {
        
        NSArray *timeArray = [self.lrcContent.timerArray[i] componentsSeparatedByString:@":"];
        float lrcTime = [timeArray[0] intValue] * 60 + [timeArray[1] floatValue];
        if (currentTime > lrcTime) {
            
            self.currentRow = i;
        }
    }
    [self.tableView reloadData];
    [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.currentRow inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    [self createSubViews];
}
- (void)createSubViews {
    
    self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"28131977_1383101943208"]];
    
    /** 歌手圓圖 */
    self.imageViewOfSinger = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds) * 0.75, CGRectGetWidth(self.view.bounds) * 0.75)];
    _imageViewOfSinger.wh_centerX = self.view.wh_centerX;
    _imageViewOfSinger.wh_centerY = self.view.wh_centerY * 0.8;
    [self.view addSubview:_imageViewOfSinger];
    self.imageViewOfSinger.clipsToBounds = YES;
    self.imageViewOfSinger.layer.cornerRadius = self.imageViewOfSinger.bounds.size.width / 2;
    self.imageViewOfSinger.layer.borderWidth = 2;
    
   /** 歌名 */
    self.labelOfSongName = [[UILabel alloc] initWithFrame:CGRectMake(60, 20, CGRectGetWidth(self.view.bounds) - 120, 44)];
    [self.view addSubview:_labelOfSongName];
    _labelOfSongName.textAlignment = NSTextAlignmentCenter;
    _labelOfSongName.textColor = [UIColor whiteColor];
    _labelOfSongName.font = [UIFont systemFontOfSize:20];
    
    /** 歌手 */
    self.labelOfSingerName = [[UILabel alloc] initWithFrame:CGRectMake(60, 70, CGRectGetWidth(self.view.bounds) - 120, 50)];
    [self.view addSubview:_labelOfSingerName];
    _labelOfSingerName.textAlignment = NSTextAlignmentCenter;
    _labelOfSingerName.textColor = [UIColor whiteColor];
    _labelOfSingerName.font = [UIFont systemFontOfSize:15];
    
    
    /** slider */
    self.slider = [[UISlider alloc] initWithFrame:CGRectMake(50, CGRectGetHeight(self.view.bounds) - 130, CGRectGetWidth(self.view.bounds) - 100, 30)];
    [self.view addSubview:_slider];
    [_slider setMinimumTrackImage:[UIImage imageNamed:@"player_slider_playback_left"] forState:UIControlStateNormal];
    [_slider setMaximumTrackImage:[UIImage imageNamed:@"player_slider_playback_right"] forState:UIControlStateNormal];
    [_slider setThumbImage:[UIImage imageNamed:@"player_slider_playback_thumb"] forState:UIControlStateNormal];

    /** slider兩邊的時間 */
    self.labelOfMin = [[UILabel alloc] initWithFrame:CGRectMake(0, CGRectGetHeight(self.view.bounds) - 130, 50, 30)];
    [self.view addSubview:_labelOfMin];
    _labelOfMin.textColor = [UIColor whiteColor];
    _labelOfMin.textAlignment = NSTextAlignmentCenter;
    _labelOfMin.text = @"00:00";
    
    self.labelOfMax = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.view.bounds) - 50, CGRectGetHeight(self.view.bounds) - 130, 50, 30)];
    [self.view addSubview:_labelOfMax];
    _labelOfMax.textColor = [UIColor whiteColor];
    _labelOfMax.textAlignment = NSTextAlignmentCenter;
    
    /** 自定義的playView */
    PlayView *playView = [[PlayView alloc] initWithFrame:CGRectMake(0, CGRectGetHeight(self.view.bounds) - 100, CGRectGetWidth(self.view.bounds), 100)];
    [self.view addSubview:playView];
    [playView play:^(UIButton *btn) {
        
        [self.player play];
        
    } pause:^(UIButton *btn) {
        
        [self.player pause];
    } last:^(UIButton *btn) {
        
        // 在開始播放之前, 禁用一切的app點擊事件
        UIWindow *window = [[UIApplication sharedApplication].windows lastObject];
        window.userInteractionEnabled = NO;
        // 重置當前歌曲
        [self resetPlayMusic];
        
        // 獲得上一曲
        [WHMusicTool setPlayingMusic:[WHMusicTool lastMusic]];
        
        // 播放上一曲
        [self startPlayingMusic];
        
        window.userInteractionEnabled = YES;
        
        // 恢復window的點擊為可用
        window.userInteractionEnabled = YES;
        
    } next:^(UIButton *btn) {
        
        // 在開始播放之前, 禁用一切的app點擊事件
        UIWindow *window = [[UIApplication sharedApplication].windows lastObject];
        window.userInteractionEnabled = NO;

        // 重置當前歌曲
        [self resetPlayMusic];
        
        // 獲取下一曲
        [WHMusicTool setPlayingMusic:[WHMusicTool nextMusic]];
        
        // 播放下一曲
        [self startPlayingMusic];
        
        // 恢復window的點擊為可用
        window.userInteractionEnabled = YES;
    }];
    /** 左上角的返回按鈕 */
    UIButton *buttonOfBack = [UIButton buttonWithType:UIButtonTypeCustom];
    [buttonOfBack setTitle:@"Back" forState:UIControlStateNormal];
    [self.view addSubview:buttonOfBack];
    buttonOfBack.frame = CGRectMake(10, 20, 50, 44);
    [buttonOfBack addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside];
    /** 右上角的歌詞按鈕 */
    UIButton *buttonOfLyric = [UIButton buttonWithType:UIButtonTypeCustom];
    [self.view addSubview:buttonOfLyric];
    [buttonOfLyric setTitle:@"歌詞" forState:UIControlStateNormal];
    buttonOfLyric.frame = CGRectMake(CGRectGetWidth(self.view.bounds) - 60, 20, 50, 44);
    [buttonOfLyric addTarget:self action:@selector(lyricAction:) forControlEvents:UIControlEventTouchUpInside]; 
}
- (void)createLyricTableView {
    NSArray *array = [_playingMusic.lrcname componentsSeparatedByString:@"."];
    self.lrcContent = [[LrcParser alloc] init];
    [_lrcContent parserLrc:array.firstObject type:array.lastObject];
     
    self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds) - 200) style:UITableViewStylePlain];
    [self.view addSubview:_tableView];
    _tableView.delegate = self;
    _tableView.dataSource = self;
    
    [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"pool"];
    _tableView.hidden = YES;
    _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    
    return _lrcContent.wordArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"pool"];
    
    cell.textLabel.text =  _lrcContent.wordArray[indexPath.row];
    
    if (indexPath.row == self.currentRow) {
        
        cell.textLabel.textColor = [UIColor redColor];
        cell.textLabel.font = [UIFont systemFontOfSize:20];
    } else {
    
        cell.textLabel.textColor = [UIColor lightGrayColor];
        cell.textLabel.font = [UIFont systemFontOfSize:15];
    }
    
    cell.textLabel.textAlignment = NSTextAlignmentCenter;
    cell.backgroundColor = [UIColor clearColor];
    return cell;
}
- (void)lyricAction:(UIButton *)btn {

    if (self.tableView.hidden) {
        
        self.tableView.hidden = NO;
        btn.selected = YES;
    } else {
    
        self.tableView.hidden = YES;
        btn.selected = NO;
    }
}
@end

額 有點亂. 不過仔細屢屢就明白了!!!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,791評論 6 545
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 99,795評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,943評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,057評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,773評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,106評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,082評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,282評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 49,793評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,507評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,741評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,220評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,929評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,325評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,661評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,482評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,702評論 2 380

推薦閱讀更多精彩內容