logo头像

内行看门道,外行看人行道~

单例实现声音播放工具类(支持多个声音同时播放)

一直疑惑游戏里面的多个音效同时播放是怎么实现的,今天终于弄明白了,单例实现,看代码:
YJAudioTool.h

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

@interface YJAudioTool : NSObject

+(instancetype)sharedAudioTool;

//播放音乐(可以同时播放多个音乐)
-(AVAudioPlayer *)playMusic:(NSString *)fileName;
-(void)pauseMusic:(NSString *)fileName;
-(void)stopMusic:(NSString *)fileName;


//播放音效
-(void)playSound:(NSString *)soundName;
-(void)disposeSound:(NSString *)soundName;//摧毁音效

@end

YJAudioTool.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
#import "YJAudioTool.h"
static YJAudioTool *_instance = nil;

@interface YJAudioTool()
@property (nonatomic,strong)NSMutableDictionary *musicPlayers;
@property (nonatomic,strong)NSMutableDictionary *soundIDs;
@end

@implementation YJAudioTool
+ (instancetype)sharedAudioTool{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (_instance == nil) {
_instance = [[YJAudioTool alloc]init];
}
});
return _instance;
}
+(id)allocWithZone:(struct _NSZone *)zone{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (_instance == nil) {
_instance = [super allocWithZone:zone];
}
});
return _instance;
}

-(instancetype)init{
__block YJAudioTool *temp = self;

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if ((temp = [super init]) != nil) {
//初始化变量
_musicPlayers = [NSMutableDictionary dictionaryWithCapacity:3];
_soundIDs = [NSMutableDictionary dictionaryWithCapacity:3];
}
});
self = temp;
return self;
}

-(id)copy{
return _instance;
}
-(id)mutableCopy{
return _instance;
}

//单例方法
-(AVAudioPlayer *)playMusic:(NSString *)fileName{
if (!fileName || fileName.length == 0) {
return nil;
}
AVAudioPlayer *player = self.musicPlayers[fileName];
if (!player) {
NSURL *musicURL = [[NSBundle mainBundle]URLForResource:fileName withExtension:nil];
if (!musicURL) {
return nil;
}
player = [[AVAudioPlayer alloc]initWithContentsOfURL:musicURL error:nil];
if(![player prepareToPlay]){
return nil;
}
self.musicPlayers[fileName] = player;
}
if (!player.isPlaying) {
[player play];
}
return player;
}
//暂停
-(void)pauseMusic:(NSString *)fileName{
if (!fileName || fileName.length == 0) {
return;
}
AVAudioPlayer *player = self.musicPlayers[fileName];
if(player.isPlaying){
[player pause];
}
}
//停止
-(void)stopMusic:(NSString *)fileName{
if (!fileName || fileName.length == 0) {
return;
}
AVAudioPlayer *player = self.musicPlayers[fileName];
[player stop];
}

//播放音效
-(void)playSound:(NSString *)soundName{
if (!soundName || soundName.length == 0) {
return;
}
SystemSoundID soundID = (int)[self.soundIDs[soundName] unsignedLongValue];
if (!soundID) {
NSURL *url = [[NSBundle mainBundle]URLForResource:soundName withExtension:nil];
if (!url){
return;
}

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

self.soundIDs[soundName] = @(soundID);
}
AudioServicesPlaySystemSound(soundID);
}

// 摧毁音效
-(void)disposeSound:(NSString *)soundName{
if (!soundName) return;

SystemSoundID soundID = (int)[self.soundIDs[soundName] unsignedLongValue];

if (soundID) {
AudioServicesDisposeSystemSoundID(soundID);

[self.soundIDs removeObjectForKey:soundName]; //音效被摧毁,那么对应的对象应该从缓存中移除
}
}


@end

viewcontroller中的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-(void)firstStartMusic{
NSLog(@"播放声音1");
[[YJAudioTool sharedAudioTool]playMusic:@"123.mp3"];

}
-(void)firstPauseMusic{
NSLog(@"暂停声音1");
[[YJAudioTool sharedAudioTool]pauseMusic:@"123.mp3"];
}

-(void)secStartMusic{
NSLog(@"播放声音2");
[[YJAudioTool sharedAudioTool]playMusic:@"林俊杰-江南.mp3"];
}
-(void)secPauseMusic{
NSLog(@"暂停声音2");
[[YJAudioTool sharedAudioTool]pauseMusic:@"林俊杰-江南.mp3"];
}

个人疑问:每次播放一个声音之前,根据音效的名字创建的每一个player对象,都存放到了一个数组中,这样是不是违背了单例的原则?有大神明白的话,下方留言,不吝赐教。

微信打赏

赞赏是不耍流氓的鼓励