• iOS- 优化与封装 APP音效的播放


    1.关于音效                    

    音效又称短音频,是一个声音文件,在应用程序中起到点缀效果,用于提升应用程序的整体用户体验。
     
    我们手机里常见的APP几乎都少不了音效的点缀。
     
    显示实现音效并不复杂,但对我们App很重要!
     

    2.音效播放                  

    2.1.首先实现我们需要导入框架AudioToolbox.framework 

    2.2.为了优化效播放,减少每次重复加载音效播放,我们将加载音效设为单例

    实现单例 —— 将我在前几篇文章说过封装好的的单例宏 直接引用 Singleton.h

    创建

    Singleton.h
    #import <Foundation/Foundation.h>
    #import "Singleton.h"
    
    @interface SoundTools : NSObject
    
    //单例宏
    singleton_interface(SoundTools)
    
    //要播放的音效名
    - (void)playSoundWithName:(NSString *)name;
    
    @end

    将APP要用到的音效添加到新建的bound里去

    如图:

    创建

    Singleton.m
    #import "SoundTools.h"
    #import <AudioToolbox/AudioToolbox.h>
    
    /**
     将所有的音频文件在此单例中统一处理
     */
    
    @interface SoundTools()
    {
        NSDictionary    *_soundDict; // 音频字典
    }
    
    @end
    
    @implementation SoundTools
    singleton_implementation(SoundTools)
    
    - (id)init
    {
        self = [super init];
        
        if (self) {
            // 完成所有音频文件的加载工作
            _soundDict = [self loadSounds];
        }
        
        return self;
    }

    2.3.启动系统声音服务                   

    系统声音服务通过SystemSoundID来播放声音文件,对于同一个声音文件,可以创建多个SystemSoundID

    系统声音服务是一套C语言的框架

    为了提高应用程序性能,避免声音文件被重复加载,通常采用单例模式处理系统声音的播放

    Singleton.m 实现
    #pragma mark 加载指定的音频文件
    - (SystemSoundID)loadSoundWithURL:(NSURL *)url
    {
        SystemSoundID soundID = 0;
        
        AudioServicesCreateSystemSoundID((__bridge CFURLRef)(url), &soundID);
        
        return soundID;
    }

    2.4.加载bound里所有的音效文件,并记录进全局的字典中      

    #pragma mark 加载所有的音频文件
    - (NSDictionary *)loadSounds
    {
        // 思考:如何直到加载哪些音频文件呢?
        // 建立一个sound.bundle,存放所有的音效文件
        // 在程序执行时,直接遍历bundle中的所有文件
        // 1. 取出bundle的路径名
        NSString *mainBundlPath = [[NSBundle mainBundle] bundlePath];
        NSString *bundlePath =[mainBundlPath stringByAppendingPathComponent:@"sound.bundle"];
        
        // 2. 遍历目录
        NSArray *array = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:bundlePath error:nil];
        
        // 3. 遍历数组,创建SoundID,如何使用?
        NSMutableDictionary *dictM = [NSMutableDictionary dictionaryWithCapacity:array.count];
        
        [array enumerateObjectsUsingBlock:^(NSString *fileName, NSUInteger idx, BOOL *stop) {
            // 1> 拼接URL
            NSString *filePath = [bundlePath stringByAppendingPathComponent:fileName];
            NSURL *fileURL = [NSURL fileURLWithPath:filePath];
            
            SystemSoundID soundID = [self loadSoundWithURL:fileURL];
            
            // 将文件名作为键值
            [dictM setObject:@(soundID) forKey:fileName];
        }];
        
        return dictM;
    }

    2.5.播放音频                        
    注意 断言:在项目开发中,防止被无意中修改音效名,找不到要播放的音效文件

    #pragma mark - 播放音频
    - (void)playSoundWithName:(NSString *)name
    {
        SystemSoundID soundID = [_soundDict[name] unsignedLongValue];
        NSLog(@"%ld",soundID);
        //断言它必须大于0;
        NSAssert(soundID > 0, @"%@ 声音文件不存在!", name);
        
        AudioServicesPlaySystemSound(soundID);
    }

    在控制器里调用按钮的点击事情即可

    - (void)clickMe
    {
        [[SoundTools sharedSoundTools] playSoundWithName:@"game_overs.mp3"];
    
    }

    2.6.优化之前的代码 —— 每次都会重复加载新的音效

    //    NSURL *url = [[NSBundle mainBundle] URLForResource:@"bullet.mp3" withExtension:nil];
    //    SystemSoundID soundID = 0;
    //    
    //    // 创建声音,并且生成soundID的数值
    //    AudioServicesCreateSystemSoundID((__bridge CFURLRef)(url), &soundID);
    //    
    //    // 播放声音
    //    // 同样遵守苹果的静音原则,如果用户静音,会震动!提示用户注意!
    ////    AudioServicesPlayAlertSound(<#SystemSoundID inSystemSoundID#>)
    //    // 只播放声音,遵守苹果的静音原则 HIG
    //    AudioServicesPlaySystemSound(soundID);
    //    
    //    NSLog(@"%ld", soundID);

    作者: 清澈Saup
    出处: http://www.cnblogs.com/qingche/
    本文版权归作者和博客园共有,欢迎转载,但必须保留此段声明,且在文章页面明显位置给出原文连接。

  • 相关阅读:
    设计模式之单例模式
    设计模式之组合模式
    SVN搭建简单教程
    添加Silverlight应用到HTML
    动态修改配置文件
    Ajax
    jQuery 事件方法
    Java和JavaScript对账户实现掩码并四个一组分隔
    一种简单实现当前时间是否在工作时间内的方法
    Postman接口自动化测试实例用到的完整的SM2前端加密算法代码
  • 原文地址:https://www.cnblogs.com/qingche/p/3600610.html
Copyright © 2020-2023  润新知