在 iOS 和 Swift 中播放声音而不会发生内存泄漏的可重用扩展?

Reusable extension to play sound without memory leak in iOS and Swift?

播放声音的代码非常冗长,如果可能的话,我想创建一个 AVAudioSession 的扩展。我这样做的方式是将一个对象分配给一个变量,但需要 help/advise 了解如何设置此函数以使其可重用和优化。

这是我的:

func playSound(name: String, extension: String = "mp3") {
    let sound = NSBundle.mainBundle().URLForResource(name, withExtension: extension)

    do {
        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
        try AVAudioSession.sharedInstance().setActive(true)

        UIApplication.sharedApplication().beginReceivingRemoteControlEvents()

        audioPlayer = try AVAudioPlayer(contentsOfURL: sound!)
        audioPlayer?.prepareToPlay()
        audioPlayer?.play()
    } catch { }
}

我想我必须在这个函数之外创建 audioPlayer 变量,否则我很难玩任何东西。也许它可以自给自足?我希望像这样使用它:

AVAudioSession.sharedInstance().play("bebop")

这是我发现的添加声音的最佳方式

文件名为 shootMissile.wav

func shootMissileSound() {
    if let soundURL = NSBundle.mainBundle().URLForResource("shootMissile", withExtension: "wav") {
        var mySound: SystemSoundID = 0
        AudioServicesCreateSystemSoundID(soundURL, &mySound)
        AudioServicesPlaySystemSound(mySound);
    }
}

直接从您的示例中获取代码,我看到两个选项:

1) 你有什么特别的理由想把它作为AVAudioSession的扩展吗?如果没有,就自己做服务吧!

class AudioPlayerService {

    static let sharedInstance = AudioPlayerService()

    var audioPlayer: AVAudioPlayer?

    func playSound(name: String, extension: String = "mp3") {
        let sound = NSBundle.mainBundle().URLForResource(name, withExtension: extension)

        do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
            try AVAudioSession.sharedInstance().setActive(true)

            UIApplication.sharedApplication().beginReceivingRemoteControlEvents()

            audioPlayer = try AVAudioPlayer(contentsOfURL: sound!)
            audioPlayer?.prepareToPlay()
            audioPlayer?.play()
        } catch { }
    }

}

2) 如果你需要把它作为AVAudioSession的扩展,那么看看associated objects

extension AVAudioSession {

    private struct AssociatedKeys {
        static var AudioPlayerTag = "AudioPlayerTag"
    }

    var audioPlayer: AVAudioPlayer? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.AudioPlayerTag) as? AVAudioPlayer
        }

        set {
            if let newValue = newValue {
                objc_setAssociatedObject(
                    self,
                    &AssociatedKeys.AudioPlayerTag,
                    newValue as AVAudioPlayer?,
                    .OBJC_ASSOCIATION_RETAIN_NONATOMIC
                )
            }
        }
    }

    func playSound(name: String, extension: String = "mp3") {
        let sound = NSBundle.mainBundle().URLForResource(name, withExtension: extension)

        do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
            try AVAudioSession.sharedInstance().setActive(true)

            UIApplication.sharedApplication().beginReceivingRemoteControlEvents()

            audioPlayer = try AVAudioPlayer(contentsOfURL: sound!)
            audioPlayer?.prepareToPlay()
            audioPlayer?.play()
        } catch { }
    }

}