今天给同学们带来音频,音乐,和视频播放相关的案例那么废话不多说直接上代码!先看演示示例:
//
// ZZMusic.h
// 05-音乐播放器
//
// Created by 周昭 on 2017/3/20.
// Copyright © 2017年 ZZ. All rights reserved.
//
#warning - 对模型的处理借助MJExtension
#import <Foundation/Foundation.h>
@interface ZZMusic : NSObject
@property (copy, nonatomic) NSString *name;
@property (copy, nonatomic) NSString *filename;
@property (copy, nonatomic) NSString *singer;
@property (copy, nonatomic) NSString *singerIcon;
@property (copy, nonatomic) NSString *icon;
@property (nonatomic, assign, getter = isPlaying) BOOL playing;
@end
//
// ZZMusic.m
// 05-音乐播放器
//
// Created by 周昭 on 2017/3/20.
// Copyright © 2017年 ZZ. All rights reserved.
//
#import "ZZMusic.h"
@implementation ZZMusic
@end
//
// ZZMusicCell.h
// 05-音乐播放器
//
// Created by 周昭 on 2017/3/20.
// Copyright © 2017年 ZZ. All rights reserved.
//
#import <UIKit/UIKit.h>
@class ZZMusic;
@interface ZZMusicCell : UITableViewCell
+ (instancetype)cellWithTableView:(UITableView *)tableView;
@property (nonatomic, strong) ZZMusic *music;
@end
//
// ZZMusicCell.m
// 05-音乐播放器
//
// Created by 周昭 on 2017/3/20.
// Copyright © 2017年 ZZ. All rights reserved.
//
#import "ZZMusicCell.h"
#import "ZZMusic.h"
#import "Colours.h"
#import "UIImage+ZZ.h"
@interface ZZMusicCell()
/**
* 定时器
*/
@property (nonatomic, strong) CADisplayLink *link;
@end
@implementation ZZMusicCell
- (CADisplayLink *)link
{
if (!_link) {
self.link = [CADisplayLink displayLinkWithTarget:self selector:@selector(update)];
}
return _link;
}
+ (instancetype)cellWithTableView:(UITableView *)tableView
{
static NSString *ID = @"music";
ZZMusicCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[ZZMusicCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
return cell;
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
self.backgroundColor = [UIColor clearColor];
self.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"backgroundImage"]];
}
return self;
}
- (void)setMusic:(ZZMusic *)music
{
_music = music;
self.textLabel.text = music.name;
self.detailTextLabel.text = music.singer;
self.imageView.image = [UIImage circleImageWithName:music.singerIcon borderWidth:2 borderColor:[UIColor skyBlueColor]];
if (music.isPlaying) {
[self.link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
} else { // 停止动画
[self.link invalidate];
self.link = nil;
self.imageView.transform = CGAffineTransformIdentity;
}
}
/**
* 8秒转一圈, 45°/s
*/
- (void)update
{
// 1/60秒 * 45
// 规定时间内转动的角度 == 时间 * 速度
CGFloat angle = self.link.duration * M_PI_4;
self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, angle);
}
- (void)dealloc
{
// 移除定时器
[self.link removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
@end
//
// UIImage+ZZ.h
// 05-音乐播放器
//
// Created by 周昭 on 2017/3/20.
// Copyright © 2017年 ZZ. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIImage (ZZ)
+ (instancetype)circleImageWithName:(NSString *)name borderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor;
@end
//
// UIImage+ZZ.m
// 05-音乐播放器
//
// Created by 周昭 on 2017/3/20.
// Copyright © 2017年 ZZ. All rights reserved.
//
#import "UIImage+ZZ.h"
@implementation UIImage (ZZ)
+ (instancetype)circleImageWithName:(NSString *)name borderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor
{
// 1.加载原图
UIImage *oldImage = [UIImage imageNamed:name];
// 2.开启上下文
CGFloat imageW = oldImage.size.width + 2 * borderWidth;
CGFloat imageH = oldImage.size.height + 2 * borderWidth;
CGSize imageSize = CGSizeMake(imageW, imageH);
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0);
// 3.取得当前的上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 4.画边框(大圆)
[borderColor set];
CGFloat bigRadius = imageW * 0.5; // 大圆半径
CGFloat centerX = bigRadius; // 圆心
CGFloat centerY = bigRadius;
CGContextAddArc(ctx, centerX, centerY, bigRadius, 0, M_PI * 2, 0);
CGContextFillPath(ctx); // 画圆
// 5.小圆
CGFloat smallRadius = bigRadius - borderWidth;
CGContextAddArc(ctx, centerX, centerY, smallRadius, 0, M_PI * 2, 0);
// 裁剪(后面画的东西才会受裁剪的影响)
CGContextClip(ctx);
// 6.画图
[oldImage drawInRect:CGRectMake(borderWidth, borderWidth, oldImage.size.width, oldImage.size.height)];
// 7.取图
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
// 8.结束上下文
UIGraphicsEndImageContext();
return newImage;
}
@end
//
// ZZAudioTool.h
// 05-音乐播放器
//
// Created by 周昭 on 2017/3/20.
// Copyright © 2017年 ZZ. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
@interface ZZAudioTool : NSObject
/**
* 播放器
*/
@property(nonatomic, strong) AVAudioPlayer *player;
/**
* 创建单例
*/
+ (instancetype)shareInstance;
/**
* 播放音效
*
* @param filename 音效文件名
*/
+ (void)playSound:(NSString *)filename;
/**
* 销毁音效
*
* @param filename 音效文件名
*/
+ (void)disposeSound:(NSString *)filename;
/**
* 播放音乐
*
* @param filename 音乐文件名
*/
+ (AVAudioPlayer *)playMusic:(NSString *)filename;
/**
* 暂停音乐
*
* @param filename 音乐文件名
*/
+ (void)pauseMusic:(NSString *)filename;
/**
* 停止音乐
*
* @param filename 音乐文件名
*/
+ (void)stopMusic:(NSString *)filename;
/**
* 返回当前正在播放的音乐播放器
*/
+ (AVAudioPlayer *)currentPlayingAudioPlayer;
@end
//
// ZZAudioTool.m
// 05-音乐播放器
//
// Created by 周昭 on 2017/3/20.
// Copyright © 2017年 ZZ. All rights reserved.
//
#import "ZZAudioTool.h"
@implementation ZZAudioTool
/**
* 存放所有的音频ID
* 字典: filename作为key, soundID作为value
*/
static NSMutableDictionary *_soundIDDict;
/**
* 存放所有的音乐播放器
* 字典: filename作为key, audioPlayer作为value
*/
static NSMutableDictionary *_audioPlayerDict;
/**
* 返回请求单例对象
*/
+ (instancetype)shareInstance
{
static ZZAudioTool *audioTool;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (audioTool == nil) {
audioTool = [[ZZAudioTool alloc] init];
}
});
return audioTool;
}
/**
* 初始化
*/
+ (void)initialize
{
_soundIDDict = [NSMutableDictionary dictionary];
_audioPlayerDict = [NSMutableDictionary dictionary];
// 设置音频会话类型
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategorySoloAmbient error:nil];
[session setActive:YES error:nil];
}
/**
* 播放音效
*
* @param filename 音效文件名
*/
+ (void)playSound:(NSString *)filename
{
if (!filename) return;
// 1.从字典中取出soundID
SystemSoundID soundID = [_soundIDDict[filename] unsignedLongValue];
if (!soundID) { // 创建
// 加载音效文件
NSURL *url = [[NSBundle mainBundle] URLForResource:filename withExtension:nil];
if (!url) return;
// 创建音效ID
AudioServicesCreateSystemSoundID((__bridge CFURLRef)url, &soundID);
// 放入字典
_soundIDDict[filename] = @(soundID);
}
// 2.播放
AudioServicesPlaySystemSound(soundID);
}
/**
* 销毁音效
*
* @param filename 音效文件名
*/
+ (void)disposeSound:(NSString *)filename
{
if (!filename) return;
SystemSoundID soundID = [_soundIDDict[filename] unsignedLongValue];
if (soundID) {
// 销毁音效ID
AudioServicesDisposeSystemSoundID(soundID);
// 从字典中移除
[_soundIDDict removeObjectForKey:filename];
}
}
/**
* 播放音乐
*
* @param filename 音乐文件名
*/
+ (AVAudioPlayer *)playMusic:(NSString *)filename
{
if (!filename) return nil;
// 1.从字典中取出audioPlayer
AVAudioPlayer *audioPlayer = _audioPlayerDict[filename];
if (!audioPlayer) { // 创建
// 加载音乐文件
NSURL *url = [[NSBundle mainBundle] URLForResource:filename withExtension:nil];
if (!url) return nil;
// 创建audioPlayer
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
// 缓冲
[audioPlayer prepareToPlay];
// audioPlayer.enableRate = YES;
// audioPlayer.rate = 10.0;
// 放入字典
_audioPlayerDict[filename] = audioPlayer;
}
// 2.播放
if (!audioPlayer.isPlaying) {
[audioPlayer play];
}
return audioPlayer;
}
/**
* 暂停音乐
*
* @param filename 音乐文件名
*/
+ (void)pauseMusic:(NSString *)filename
{
if (!filename) return;
// 1.从字典中取出audioPlayer
AVAudioPlayer *audioPlayer = _audioPlayerDict[filename];
// 2.暂停
if (audioPlayer.isPlaying) {
[audioPlayer pause];
}
}
/**
* 停止音乐
*
* @param filename 音乐文件名
*/
+ (void)stopMusic:(NSString *)filename
{
if (!filename) return;
// 1.从字典中取出audioPlayer
AVAudioPlayer *audioPlayer = _audioPlayerDict[filename];
// 2.暂停
if (audioPlayer.isPlaying) {
[audioPlayer stop];
// 直接销毁
[_audioPlayerDict removeObjectForKey:filename];
}
}
/**
* 返回当前正在播放的音乐播放器
*/
+ (AVAudioPlayer *)currentPlayingAudioPlayer
{
for (NSString *filename in _audioPlayerDict) {
AVAudioPlayer *audioPlayer = _audioPlayerDict[filename];
if (audioPlayer.isPlaying) {
return audioPlayer;
}
}
return nil;
}
@end
//
// ZZMusicsController.h
// 05-音乐播放器
//
// Created by 周昭 on 2017/3/20.
// Copyright © 2017年 ZZ. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ZZMusicsController : UIViewController
@end
//
// ZZMusicsController.m
// 05-音乐播放器
//
// Created by 周昭 on 2017/3/20.
// Copyright © 2017年 ZZ. All rights reserved.
//
#import "ZZMusicsController.h"
#import "ZZMusic.h"
#import "ZZMusicCell.h"
#import "ZZAudioTool.h"
#import "MJExtension.h"
#import "NSString+ZZ.h"
#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>
@interface ZZMusicsController ()<UITableViewDelegate,UITableViewDataSource,AVAudioPlayerDelegate>
@property (nonatomic, strong) NSArray *musics;
@property (nonatomic, strong) AVAudioPlayer *currentPlayingAudioPlayer;
@property (nonatomic, weak) UITableView *tableView;
@property (nonatomic, weak) UIImageView *imgView;
@end
@implementation ZZMusicsController
#pragma mark - 懒加载
- (NSArray *)musics
{
if (!_musics) {
self.musics = [ZZMusic objectArrayWithFilename:@"Musics.plist"];
}
return _musics;
}
- (void)viewDidLoad {
[super viewDidLoad];
// 0.设置标题&背景
[self setUpTitle];
// 1.初始化tableView
[self setUpTableView];
}
#pragma mark - setUp 初始化
- (void)setUpTableView
{
// 0.创建tableView
UITableView *tableView = [[UITableView alloc] init];
tableView.delegate = self;
tableView.dataSource = self;
tableView.tableFooterView = [[UIView alloc] init];
// 1.设置背景
UIImageView *imgView = [[UIImageView alloc] init];
imgView.frame = self.view.frame;
imgView.image = [UIImage imageNamed:@"backgroundImage"];
tableView.backgroundView = imgView;
tableView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[self.view addSubview:tableView];
self.tableView = tableView;
}
- (void)setUpTitle
{
// 0.设置标题
self.title = NSLocalizedString(@"音乐播放器", nil);
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.musics.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.创建cell
ZZMusicCell *cell = [ZZMusicCell cellWithTableView:tableView];
// 2.设置cell的数据
cell.music = self.musics[indexPath.row];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 70;
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
// 停止音乐
ZZMusic *music = self.musics[indexPath.row];
[ZZAudioTool stopMusic:music.filename];
// 再次传递模型
ZZMusicCell *cell = (ZZMusicCell *)[tableView cellForRowAtIndexPath:indexPath];
music.playing = NO;
cell.music = music;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// 取出当前点击的cell
ZZMusicCell *cell = (ZZMusicCell *)[tableView cellForRowAtIndexPath:indexPath];
// 取出要播放的音乐
ZZMusic *music = self.musics[indexPath.row];
if (music.playing) {
[ZZAudioTool pauseMusic:music.filename];
music.playing = NO;
cell.music = music;
} else {
AVAudioPlayer *audioPlayer = [ZZAudioTool playMusic:music.filename];
audioPlayer.delegate = self;
self.currentPlayingAudioPlayer = audioPlayer;
// 在锁屏界面显示歌曲信息
[self showInfoInLockedScreen:music];
// 再次传递模型
music.playing = YES;
cell.music = music;
}
}
/**
* 在锁屏界面显示歌曲信息
*/
- (void)showInfoInLockedScreen:(ZZMusic *)music
{
NSMutableDictionary *info = [NSMutableDictionary dictionary];
// 标题(音乐名称)
info[MPMediaItemPropertyTitle] = music.name;
// 作者
info[MPMediaItemPropertyArtist] = music.singer;
// 专辑
info[MPMediaItemPropertyAlbumTitle] = music.singer;
// 图片
info[MPMediaItemPropertyArtwork] = [[MPMediaItemArtwork alloc] initWithImage:[UIImage imageNamed:music.icon]];
[MPNowPlayingInfoCenter defaultCenter].nowPlayingInfo = info;
}
#pragma mark - AVAudioPlayerDelegate
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
// 计算下一行
NSIndexPath *selectedPath = [self.tableView indexPathForSelectedRow];
NSInteger nextRow = selectedPath.row + 1;
if (nextRow == self.musics.count) {
nextRow = 0;
}
#warning 停止上一首歌的转圈
// 再次传递模型
ZZMusicCell *cell = (ZZMusicCell *)[self.tableView cellForRowAtIndexPath:selectedPath];
ZZMusic *music = self.musics[selectedPath.row];
music.playing = NO;
cell.music = music;
// 播放下一首歌
NSIndexPath *currentPath = [NSIndexPath indexPathForRow:nextRow inSection:selectedPath.section];
[self.tableView selectRowAtIndexPath:currentPath animated:YES scrollPosition:UITableViewScrollPositionTop];
[self tableView:self.tableView didSelectRowAtIndexPath:currentPath];
}
/**
* 音乐播放器被打断(打\接电话)
*/
- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player
{
NSLog(@"audioPlayerBeginInterruption---被打断");
}
/**
* 音乐播放器停止打断(打\接电话)
*/
- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player withOptions:(NSUInteger)flags
{
NSLog(@"audioPlayerEndInterruption---停止打断");
[player play];
}
@end