音频播放
音频播放一般有两种途径,第一种是通过AVFoundation框架的 AVPlayer,第二种是通过AVFoundation框架的AVAudioSession.
关键类/结构体
- AVPlayer
- AVPlayerItem
- CMTime
其中AVPlayer就是一个播放器,而AVPlayerItem就是一个要播放的资源,我们平时是不是用一个MP3播放器播放音乐,其中这个AVPlayer就是一个MP3播放器,而AVPlayerItem就是一首要播放的资源.当然我们的播放器中是不是存放了很多首歌曲?所以我们也要想办法怎么去存放很多AVPlayerItem去让AVPlayer去播放,而CMTime只是一个结构体,用来记录AVPlayerItem资源的播放进度已经这个AVPlayerItem资源的一些其他信息
关键方法
1 2 3 4 5 6 7 8 9 10 11
| - (instancetype)initWithPlayerItem:(AVPlayerItem *)item;
- (void)play;
- (void)pause;
- (void)replaceCurrentItemWithPlayerItem:(AVPlayerItem *)item;
|
代码实例
播放
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @interface ViewController ()
@property (nonatomic,strong) AVPlayer * player;
@end
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; AVPlayerItem *item = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:@"http://m1.music.126.net/gpi8Adr_-pfCuP7ZXk_F2w==/2926899953898363.mp3"]]; self.player = [[AVPlayer alloc] initWithPlayerItem:item]; [self.player play]; } @end
|
当然要有暂停功能喽
而且还要有切歌的功能哦
1 2
| [self.player replaceCurrentItemWithPlayerItem:newItem];
|
当然,我们现在这些都是零碎的代码,如何才能具体来实现一个音乐播放器呢?这时我们需要思考一下,AVPlayer这个对象应该怎么存储,我们想一想网易云音乐,当播放音乐时,是不是可以切换到音乐列表页面,但是音乐还在播放的?也就是不管页面怎么切换,我们的AVPlayer都一直存在的,而且还在播放的!!!
猜猜该怎么做?
有没有想到一个设计模式?
单例?
bingo!!!就是单例,我们只需要将单例存放到单例中这样,程序运行期间,这个AVPlayer就会一直存在.
但是如何去换一首歌呢,还记得我们上面说到了一个方法是替换当前播放器的正在播放的资源的接口么?ok,我们可以通过替换当前播放歌曲来实现上一首下一首的功能.
ok,思路有了!你可不可以来实现这个音乐播放器的单例呢?试试吧!不试怎么知道不可能呢?
写个单例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| @interface AVAudioManager () { BOOL isPlaying; BOOL isPrePare; }
@property (nonatomic,strong) AVPlayer * player;
@end
@implementation AVAudioManager
+ (instancetype)sharedManager{ static AVAudioManager *manager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ manager = [AVAudioManager new]; }); return manager; }
- (void)playWithURL:(NSString *)playerItemURL{ AVPlayerItem *item = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:playerItemURL]]; [item addObserver:self forKeyPath:@"status" options:(NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew) context:nil]; [self.player replaceCurrentItemWithPlayerItem:item]; }
- (void)play{ if (!isPrePare) { return; } [self.player play]; isPlaying = YES; }
- (void)pause{ if (!isPlaying) { return; } [self.player pause]; isPlaying = NO; }
#pragma mark - 观察者
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{ NSLog(@"%@,%@",keyPath,change); AVPlayerItemStatus status = [change[@"new"] integerValue]; switch (status) { case AVPlayerItemStatusReadyToPlay: isPrePare = YES; [self play]; break; case AVPlayerItemStatusFailed: NSLog(@"音乐加载失败"); break; case AVPlayerItemStatusUnknown: NSLog(@"音乐未知"); break; default: break; } }
#pragma mark - lazy load - (AVPlayer *)player{ if (!_player) { _player = [AVPlayer new]; } return _player; } @end
|
播放
写完了这个单例后,我们想播放音乐时,只需要执行下面的代码就行了.
1 2
| AVAudioManager *manager = [AVAudioManager sharedManager] [manager playWithURL:@"http://m1.music.126.net/gpi8Adr_-pfCuP7ZXk_F2w==/2926899953898363.mp3"]
|
暂停
这样当这个单例中的AVPlayer对象加载完AVPlayerItem后就会自动播放.然后当我们想暂停时,只需要执行单例的 -(void)pause方法就可以暂停了.
1 2
| [[AVAudioManager sharedManager] pause];
|
继续播放
同样的道理,当我们暂停后可以调用play方法播放
1 2
| [[AVAudioManager sharedManager] play];
|
延展知识点