CYC-AVPlayer播放器的简单使用

AVPlayer播放器 简单易懂 使用方便 相对于AudioPlayer 更适合初学者. 本次大概会涉及到 怎么播放歌曲 下一曲 暂停 下一曲 以及歌曲 的时间 随着进度 而变化 歌词的颜色变化等 代码量甚多

播放列表

model 里面的东西就不陈述了 需要什么类型,就从接口中找到  现在开始说起单例
#import <Foundation/Foundation.h>

@interface MusicListManager : NSObject
// 单例声明
+ (instancetype )shareManager;

// 数据请求 结果回调
- (void)requestDataForReloadWithBlock:(void(^)(NSArray *array))block;

// 通过下标 获取 数据模型
- (MusicListModel *)getMusicListModelAtIndex:(NSInteger )index;

// 获取有多少条数据
- (NSInteger) getAllDataArrayCount;


@end

具体实现

#import "MusicListManager.h"

@interface MusicListManager()

@property (nonatomic, retain) NSMutableArray *allDataArray;

@end



@implementation MusicListManager


// 单例
+ (instancetype )shareManager

{
    // 新的方法 跟之前的一样
    static MusicListManager  *manager = nil;

    static dispatch_once_t onceToken;

    dispatch_once (&onceToken, ^{

         manager = [[[self class] alloc] init];

    });

    return manager;
}


// 数据请求  用block 方法 进行回调
- (void)requestDataForReloadWithBlock:(void(^)(NSArray *array))block
{
    // 创建子线程 做数据解析
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // 通过接口 获取数据 用数组接收
    NSArray *array = [NSArray arrayWithContentsOfURL:[NSURL URLWithString:kMusicplayerUrl]];
        // 遍历数组
    for (NSDictionary *dic in array) {
        MusicListModel *model = [[MusicListModel alloc] init];
        // model 赋值
        [model setValuesForKeysWithDictionary:dic];
        // 把model存储到数组中
        [self.allDataArray addObject:model];

    }
    // 回到主线程做结果回调
        dispatch_async(dispatch_get_main_queue(), ^{
             block(self.allDataArray);
        });

    });
}

#pragma mark -  通过下标 获取 数据模型
- (MusicListModel *)getMusicListModelAtIndex:(NSInteger )index

{
    MusicListModel *model = self.allDataArray[index];
    return model;
}

#pragma mark - 获取有多少条数据
- (NSInteger)getAllDataArrayCount
{
    return self.allDataArray.count;
}


// 懒方法
- (NSMutableArray *)allDataArray
{
    if (!_allDataArray) {
        _allDataArray = [NSMutableArray array];
    }
    return _allDataArray;
}
@end

播放界面

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>

 // 注意:AVPlayer播放器需要导入#import <AVFoundation/AVFoundation.h>


@protocol MusicPlayerManagerDelegate <NSObject>

- (void)playingWithProgress:(CGFloat)progress;

@end

@interface MusicPlayerManager : NSObject

// 通过下标获取model
@property (nonatomic,assign) NSInteger index;

// 当前播放的model模型
@property (nonatomic, strong) MusicListModel *listModel;

// 单例
+ (MusicPlayerManager *)shareMusicPlayer;

// 属性声明
// 播放器
@property (nonatomic, strong) AVPlayer *player;

// 音量调节
@property (nonatomic, assign) CGFloat volum;

// 代理声明
@property (nonatomic, assign) id<MusicPlayerManagerDelegate>delegete;

// 方法声明
// 设置播放器的Url
- (void)playingWithUrl:(NSString *)url;
// 开始播放
- (void)musicPlay;
// 暂停播放
- (void)musicPause;
// 播放状态的切换
- (BOOL)musicPlayOrPause;
// slider 滑动 设置播放进度方法 -- 声明
- (void)musicSeekToTime:(CGFloat)time;
@end

具体实现

#import "MusicPlayerManager.h"

@interface MusicPlayerManager ()
{
    // 设置播放状态
    BOOL isPlaying;
}

// 定时器  跟随播放进度
@property (nonatomic, strong) NSTimer *timer;


@end

@implementation MusicPlayerManager

// 单例
+ (MusicPlayerManager *)shareMusicPlayer
{
        // 新的方法 跟之前的一样
        static MusicPlayerManager  *manager = nil;

        static dispatch_once_t onceToken;

        dispatch_once (&onceToken, ^{

            manager = [[[self class] alloc] init];
            manager.player = [[AVPlayer alloc] init];
            manager.player.volume = 10;

        });
        return manager;
}

// 方法声明
// 设置播放器的Url
- (void)playingWithUrl:(NSString *)url
{
    // 设置items 放进播放器中 然后开始播放
    AVPlayerItem *items = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:url]];
    [self.player replaceCurrentItemWithPlayerItem:items];
    [self musicPlay];

}


// 开始播放
- (void)musicPlay
{
    self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(playingAction) userInfo:nil repeats:YES];
    isPlaying = YES;
    [self.player play];
}

// 暂停播放
- (void)musicPause
{
    if(self.timer) {
        // 让当前方法无效
        [self.timer invalidate];
        self.timer = nil;
    }
    isPlaying = NO;
    [self.player pause];
}


// 播放状态的切换
- (BOOL)musicPlayOrPause
{
    if (isPlaying) {
        [self musicPause];

        return NO;
    }else {

        [self musicPlay];

        return YES;
    }
}

#pragma mark - 音量调节的 set 和 get 方法
- (void)setVolum:(CGFloat)volum
{
    self.player.volume = volum;
}

- (CGFloat)volum
{
    return self.player.volume;
}


#pragma mark - 私有方法
#pragma mark - 播放过程中执行
- (void)playingAction
{
    // 获取播放时间
    CGFloat time = self.player.currentTime.value / self.player.currentTime.timescale;
    // 代理方法 将获取到的时间  传递到控制器
    if(self.delegete && [self.delegete performSelector:@selector(playingWithProgress:)]) {
     [self.delegete playingWithProgress:time];
    }
}

#pragma mark - slider 滑动 设置播放进度方法 -- 声明
- (void)musicSeekToTime:(CGFloat)time
{
    // 先暂停
    [self musicPause];
    // 根据传递进来的时间进行 播放跳转

    // 参数1 传递进去的时间值  time:(CGFloat)
    [self.player seekToTime:CMTimeMakeWithSeconds(time, self.player.currentTime.timescale) completionHandler:^(BOOL finished) {
        if (finished) {
            // 如果跳转完成 执行播放方法
            [self musicPlay];
        }
    }];
}
@end

歌词解析时 需要的 单例 里面具体包括怎么剪接歌词 以及时间方面的问题

#import <Foundation/Foundation.h>

@interface MusicLyricManager : NSObject

// 声明单例
+ (instancetype)shareManager;

// 格式化歌词 创建歌词模型 并且存放进数组当中
- (void)formatLricModelWithLyric:(NSString *)lyric;

// 返回模型长度
- (NSInteger)getLyricModelCount;

// 根据下标取出当前歌词
- (NSString *)lyricAtIndex:(NSInteger)index;

// 根据时间返回下标
- (NSInteger) indexOfTime:(CGFloat)time;

// 根据下标指定播放进度
- (CGFloat)progressAtIndex:(NSInteger)index;
@end

实现


#import "MusicLyricManager.h"
#import "MusicLyricModel.h"

@interface MusicLyricManager ()

@property (nonatomic, strong) NSMutableArray *allLyricModelArray;

@end


@implementation MusicLyricManager

// 声明单例
+ (instancetype)shareManager
{
    static MusicLyricManager *manager = nil;
    static dispatch_once_t onceTocken;
    dispatch_once(&onceTocken, ^{
        manager =  [[[self class]alloc] init];
        manager.allLyricModelArray = [NSMutableArray array];
    });
    return manager;
}

// 格式化歌词 创建歌词模型 并且存放进数组当中
- (void)formatLricModelWithLyric:(NSString *)lyric
{
    // 先移除数组中的元素
    [self.allLyricModelArray removeAllObjects];
    // 根据 换行符"\n" 切分
    NSArray *array = [lyric componentsSeparatedByString:@"\n"];
    // 遍历 歌词数组 格式化歌词 组建模型 并存入数组中

    for(int i = 0; i < array.count - 1; i++ ) {
        // 获取每一行歌词
        NSString *str = array[i];
        //  根据"]" 来拆分时间和歌词
        NSArray *array1 = [str componentsSeparatedByString:@"]"];
#pragma mark - 如果字符串长度小于1 直接跳出来
        if ([array1.firstObject length] < 1) {
            break;
        }

        // 时间 格式为"[00:4523]" 所以需要从1开始获取
        NSString *timeStr = [array1.firstObject substringFromIndex:1];
        // 时间格式为00:4523 所以去掉:
        NSArray *timeArray = [timeStr componentsSeparatedByString:@":"];

        // 算出总时间 以秒为单位
        CGFloat totalTime = [timeArray.firstObject floatValue] * 60 + [timeArray.lastObject floatValue];
        // 歌词
        NSString *lyricStr = array1.lastObject;
        // 初始化 歌词数据模型
        MusicLyricModel *model = [[MusicLyricModel alloc] init];

        // 歌词时间
        model.time = totalTime;

        // 歌词
        model.lyric = lyricStr;

        // 存入数组
        [self.allLyricModelArray addObject:model];

    }
}

// 返回模型长度
- (NSInteger)getLyricModelCount
{
    return self.allLyricModelArray.count;
}

// 根据下标取出当前歌词
- (NSString *)lyricAtIndex:(NSInteger)index
{
    MusicLyricModel *model = [self.allLyricModelArray objectAtIndex:index];
    return model.lyric;
}

// 根据时间返回下标
- (NSInteger) indexOfTime:(CGFloat)time
{
    NSInteger index = 0;
    for (int i = 0; i < self.allLyricModelArray.count - 1; i++) {
        MusicLyricModel *model = self.allLyricModelArray[i];
        if (model.time > time) {
            index = i - 1 > 0 ? i - 1 :0;
            break;
        }
    }
    return index;
}

// 根据下标指定播放进度
- (CGFloat)progressAtIndex:(NSInteger)index
{
    MusicLyricModel *model = self.allLyricModelArray[index];
    CGFloat time = model.time;

    return time;

}
@end

布局以及在控制器中的具体操作 将在 下一篇中提及

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值