在 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 { }
}
}
播放声音的代码非常冗长,如果可能的话,我想创建一个 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 { }
}
}