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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Small_years/article/details/81567255

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

#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

#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中的使用:

-(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对象,都存放到了一个数组中,这样是不是违背了单例的原则?有大神明白的话,下方留言,不吝赐教。

猜你喜欢

转载自blog.csdn.net/Small_years/article/details/81567255