IOS开发之——音乐播放器-功能封装(03)

一 概述

上一节介绍了音乐播放器的资源文件和将资源文件转换为对应的Model,本文介绍

  • HMMusicsTool:获取所有音乐资源和点击按钮时转换为对应的HMMusic的处理
  • HMAudioTool:真正处理音乐播放的类,处理播放、暂停、停止等操作

二 HMMusicsTool

HMMusicsTool.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#import <Foundation/Foundation.h>
#import "HMMusic.h"

@interface HMMusicsTool : NSObject
// 获取所有音乐
+ (NSArray *)musics;

// 设置当前正在播放的音乐
+ (void)setPlayingMusic:(HMMusic *)music;

// 返回当前正在播放的音乐
+ (HMMusic *)returnPlayingMusic;

// 获取下一首
+ (HMMusic *)nextMusic;

// 获取上一首
+ (HMMusic *)previouesMusic;

@end

HMMusicsTool.m

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
#import "HMMusicsTool.h"
#import "MJExtension.h"

@implementation HMMusicsTool

// 所有歌曲
static NSArray *_musics;

// 当前正在播放歌曲
static HMMusic *_playingMusic;

// 获取所有音乐
+ (NSArray *)musics
{
if (!_musics) {
_musics = [HMMusic objectArrayWithFilename:@"Musics.plist"];
}
return _musics;
}

// 设置当前正在播放的音乐
+ (void)setPlayingMusic:(HMMusic *)music
{
// 判断传入的音乐模型是否为nil
// 判断数组中是否包含该音乐模型
if (!music ||
![[self musics] containsObject:music]) {
return;
}
_playingMusic = music;
}

// 返回当前正在播放的音乐
+ (HMMusic *)returnPlayingMusic
{
return _playingMusic;
}

// 获取下一首
+ (HMMusic *)nextMusic
{
// 1.获取当前播放的索引
NSArray *_musics=[self musics];
NSUInteger currentIndex = [_musics indexOfObject:_playingMusic];
// 2.计算下一首的索引
NSInteger nextIndex = currentIndex + 1;
// 3.越界处理
if (nextIndex >= [[self musics] count]) {
nextIndex = 0;
}
// 4.取出下一首的模型返回
return [self musics][nextIndex];
}

// 获取上一首
+ (HMMusic *)previouesMusic
{
// 1.获取当前播放的索引
NSUInteger currentIndex = [[self musics] indexOfObject:_playingMusic];
// 2.计算上一首的索引
NSInteger perviouesIndex = currentIndex - 1;
// 3.越界处理
if (perviouesIndex < 0) {
perviouesIndex = [[self musics] count] - 1;
}
// 4.取出下一首的模型返回
return [self musics][perviouesIndex];
}
@end

三 HMAudioTool

HMAudioTool.h

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
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>

@interface HMAudioTool : NSObject
/**
* 播放音乐
*
* @param filename 音乐的文件名
*/
+ (AVAudioPlayer *)playMusic:(NSString *)filename;
/**
* 暂停音乐
*
* @param filename 音乐的文件名
*/
+ (void)pauseMusic:(NSString *)filename;
/**
* 停止音乐
*
* @param filename 音乐的文件名
*/
+ (void)stopMusic:(NSString *)filename;

/**
* 播放音效
*
* @param filename 音效的文件名
*/
+ (void)playSound:(NSString *)filename;
/**
* 销毁音效
*
* @param filename 音效的文件名
*/
+ (void)disposeSound:(NSString *)filename;
@end

HMAudioTool.m

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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#import "HMAudioTool.h"

@implementation HMAudioTool

+ (void)initialize
{
// 音频会话
AVAudioSession *session = [AVAudioSession sharedInstance];

// 设置会话类型(播放类型、播放模式,会自动停止其他音乐的播放)
[session setCategory:AVAudioSessionCategorySoloAmbient error:nil];

// 激活会话
[session setActive:YES error:nil];
}

/**
* 存放所有的音效ID
*/
static NSMutableDictionary *_soundIDs;
+ (NSMutableDictionary *)soundIDs
{
if (!_soundIDs) {
_soundIDs = [NSMutableDictionary dictionary];
}
return _soundIDs;
}

/**
* 存放所有的音乐播放器
*/
static NSMutableDictionary *_musicPlayers;
+ (NSMutableDictionary *)musicPlayers
{
if (!_musicPlayers) {
_musicPlayers = [NSMutableDictionary dictionary];
}
return _musicPlayers;
}

/**
* 播放音乐
*
* @param filename 音乐的文件名
*/
+ (AVAudioPlayer *)playMusic:(NSString *)filename
{
if (!filename) return nil;

// 1.取出对应的播放器
AVAudioPlayer *player = [self musicPlayers][filename];

// 2.播放器没有创建,进行初始化
if (!player) {
// 音频文件的URL
NSURL *url = [[NSBundle mainBundle] URLForResource:filename withExtension:nil];
if (!url) return nil;

// 创建播放器(一个AVAudioPlayer只能播放一个URL)
player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];

// 缓冲
if (![player prepareToPlay]) return nil;

// 存入字典
[self musicPlayers][filename] = player;
}

// 3.播放
if (!player.isPlaying) {
[player play];
}

// 正在播放
return player;
}

/**
* 暂停音乐
*
* @param filename 音乐的文件名
*/
+ (void)pauseMusic:(NSString *)filename
{
if (!filename) return;

// 1.取出对应的播放器
AVAudioPlayer *player = [self musicPlayers][filename];

// 2.暂停
if (player.isPlaying) {
[player pause];
}
}

/**
* 停止音乐
*
* @param filename 音乐的文件名
*/
+ (void)stopMusic:(NSString *)filename
{
if (!filename) return;

// 1.取出对应的播放器
AVAudioPlayer *player = [self musicPlayers][filename];

// 2.停止
[player stop];

// 3.将播放器从字典中移除
[[self musicPlayers] removeObjectForKey:filename];
}

/**
* 播放音效
*
* @param filename 音效的文件名
*/
+ (void)playSound:(NSString *)filename
{
if (!filename) return;

// 1.取出对应的音效ID
SystemSoundID soundID = [[self soundIDs][filename] unsignedLongValue];

// 2.初始化
if (!soundID) {
// 音频文件的URL
NSURL *url = [[NSBundle mainBundle] URLForResource:filename withExtension:nil];
if (!url) return;

AudioServicesCreateSystemSoundID((__bridge CFURLRef)(url), &soundID);

// 存入字典
[self soundIDs][filename] = @(soundID);
}

// 3.播放
AudioServicesPlaySystemSound(soundID);
}

/**
* 销毁音效
*
* @param filename 音效的文件名
*/
+ (void)disposeSound:(NSString *)filename
{
if (!filename) return;

// 1.取出对应的音效ID
SystemSoundID soundID = [[self soundIDs][filename] unsignedLongValue];

// 2.销毁
if (soundID) {
AudioServicesDisposeSystemSoundID(soundID);

[[self soundIDs] removeObjectForKey:filename];
}
}
@end

四 参考

  • Github-参考代码
  • Xmind原图