在 iOS 中播放简单音效的最佳方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9791491/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 17:25:38  来源:igfitidea点击:

Best ways to play simple sound effect in iOS

iphoneobjective-cios

提问by James Dunay

I'm finding a number of conflicting data about playing sounds in iOS. What is a recommended way to play just a simple "ping" sound bite every time the user touches the screen?

我发现了许多关于在 iOS 中播放声音的相互矛盾的数据。每次用户触摸屏幕时只播放简单的“ping”声音片段的推荐方法是什么?

回答by tiguero

I use this:

我用这个:

Header file:

头文件:

#import <AudioToolbox/AudioServices.h>

@interface SoundEffect : NSObject
{
    SystemSoundID soundID;
}

- (id)initWithSoundNamed:(NSString *)filename;
- (void)play;

@end

Source file:

源文件:

#import "SoundEffect.h"

@implementation SoundEffect

- (id)initWithSoundNamed:(NSString *)filename
{
    if ((self = [super init]))
    {
        NSURL *fileURL = [[NSBundle mainBundle] URLForResource:filename withExtension:nil];
        if (fileURL != nil)
        {
            SystemSoundID theSoundID;
            OSStatus error = AudioServicesCreateSystemSoundID((__bridge CFURLRef)fileURL, &theSoundID);
            if (error == kAudioServicesNoError)
                soundID = theSoundID;
        }
    }
    return self;
}

- (void)dealloc
{
    AudioServicesDisposeSystemSoundID(soundID);
}

- (void)play
{
    AudioServicesPlaySystemSound(soundID);
}

@end

You will need to create an instance of SoundEffect and direct call the method play on it.

您将需要创建一个 SoundEffect 实例并直接在其上调用 play 方法。

回答by Antonio MG

This is the best way of playing a simple sound in iOS (no more than 30 seconds):

这是在 iOS 中播放简单声音的最佳方式(不超过 30 秒):

//Retrieve audio file
NSString *path  = [[NSBundle mainBundle] pathForResource:@"soundeffect" ofType:@"m4a"];
NSURL *pathURL = [NSURL fileURLWithPath : path];

SystemSoundID audioEffect;
AudioServicesCreateSystemSoundID((__bridge CFURLRef) pathURL, &audioEffect);
AudioServicesPlaySystemSound(audioEffect);

// call the following function when the sound is no longer used
// (must be done AFTER the sound is done playing)
AudioServicesDisposeSystemSoundID(audioEffect);

回答by Oxcug

(Small amendment to the correct answer to take care of the disposing of the audio)

(对正确答案的小修正,以照顾音频的处理)

NSString *path  = [[NSBundle mainBundle] pathForResource:@"soundeffect" ofType:@"m4a"];
NSURL *pathURL = [NSURL fileURLWithPath : path];

SystemSoundID audioEffect;
AudioServicesCreateSystemSoundID((__bridge CFURLRef) pathURL, &audioEffect);
AudioServicesPlaySystemSound(audioEffect);
// Using GCD, we can use a block to dispose of the audio effect without using a NSTimer or something else to figure out when it'll be finished playing.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(30 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    AudioServicesDisposeSystemSoundID(audioEffect);
});

回答by Yiming Tang

You can use AVFoundationor AudioToolbox.

您可以使用AVFoundationAudioToolbox

Here're two examples which use the libraries separately.

这是两个单独使用库的示例。

回答by Mike Sprague

Here's an updated answer for Swift (4):

这是 Swift (4) 的更新答案:

import AudioToolbox

func playSound() {
    var soundId: SystemSoundID = 0
    guard let soundPath = Bundle.main.url(forResource: "Success7", withExtension: "wav") else {
        print("Error finding file")
        return
    }

    let error = AudioServicesCreateSystemSoundID(soundPath as CFURL, &soundId)
    if error != kAudioServicesNoError {
        print("Error loading sound")
        return
    }

    AudioServicesPlaySystemSoundWithCompletion(soundId) {
        AudioServicesDisposeSystemSoundID(soundId)
    }
}

If you have a sound effect that you want to play multiple times in a view, then you can be a little more smart about loading and disposing of the audio:

如果您想在一个视图中多次播放音效,那么您可以更聪明地加载和处理音频:

class YourViewController: UIViewController {
    fileprivate lazy var soundId: SystemSoundID? = {
        guard let soundPath = Bundle.main.url(forResource: "Success7", withExtension: "wav") else {
            return nil
        }

        var soundId: SystemSoundID = 0
        let error = AudioServicesCreateSystemSoundID(soundPath as CFURL, &soundId)
        if error != kAudioServicesNoError {
            return nil
        }

        return soundId
    }()

    func playScannedSound() {
        guard let soundId = self.soundId else {
            return
        }

        AudioServicesPlaySystemSoundWithCompletion(soundId, nil)
    }

    deinit {
        guard let soundId = self.soundId else {
            return
        }
        AudioServicesDisposeSystemSoundID(soundId)
    }

}