AVAudioPlayer 预加载的声音从内存中泄漏
AVAudioPlayer preloaded sound leaks from memory
我有一个 AVAudioPlayer 实例,它使用 audioPlayer.prepareToPlay()
将声音加载到内存中,然后在几次之后开始播放它。我有一个问题,进入后台后大约十分钟,它从内存中泄漏,我没有做好准备。在那个喂食时间之后,我没有能力再次 运行 prepareToPlay()
。如何将预加载的声音长期留在内存中?我正在准备在 applicationDidFinishLaunchingWithOptions
方法中播放的声音:
let dispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(dispatchQueue, {[weak self] in
var audioSessionError: NSError?
let audioSession = AVAudioSession.sharedInstance()
NSNotificationCenter.defaultCenter().addObserver(self!, selector: "handleInterruption:", name: AVAudioSessionInterruptionNotification, object: nil)
audioSession.setActive(true, error: nil)
if (audioSession.setCategory(AVAudioSessionCategoryPlayback, error: &audioSessionError)) {
println("Successfully set the audio session")
} else {
println("Could not set the audio session")
}
let filePath = NSBundle.mainBundle().pathForResource("sound", ofType:"mp3")
let fileData = NSData(contentsOfFile: filePath!, options: .DataReadingMappedIfSafe, error: nil)
var error:NSError?
self!.audioPlayer = AVAudioPlayer(data: fileData, error: &error)
self!.audioPlayer?.numberOfLoops = -1
self!.audioPlayer?.delegate = self
if (self?.audioPlayer?.prepareToPlay() != false) {
println("Successfully prepared for playing")
} else {
println("Failed to prepare for playing")
}
})
然后在 didReceiveRemoteNotification
我试图在后台播放它:self.audioPlayer?.play()
,它 returns true
。可能它有效,但在大约 10 - 20 分钟后它不起作用。并注意 .play()
现在 returns false
.
禁用ARC(自动引用计数)以手动释放和释放audioPlayer
是否有意义?
也许我需要使用较低级别的 API,例如 OpenAL
?但是我不会使用它,因为它在 iOS 9 中已被弃用,以后我将需要在没有 OpenAL
.
的情况下重写它
还有什么想法吗?也许我需要将 Audio Units
与 RemoteIO
一起使用?如果可行,请提供一些示例。
也许有像 ObjectAL
这样的第三方框架 - OpenAL
的简单实现。据我所知,它在 iOS 9.
中可用
这些方法只是我的假设。但他们的主要问题保持不变:这些方法会在后台运行吗?
您应该只禁用 ARC。当你进入背景时,如果你不使用它,它就会被释放。在 Swift 中创建 AVAudioPlayer 作为 Unmanaged<T>
对象。
我有一个 AVAudioPlayer 实例,它使用 audioPlayer.prepareToPlay()
将声音加载到内存中,然后在几次之后开始播放它。我有一个问题,进入后台后大约十分钟,它从内存中泄漏,我没有做好准备。在那个喂食时间之后,我没有能力再次 运行 prepareToPlay()
。如何将预加载的声音长期留在内存中?我正在准备在 applicationDidFinishLaunchingWithOptions
方法中播放的声音:
let dispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(dispatchQueue, {[weak self] in
var audioSessionError: NSError?
let audioSession = AVAudioSession.sharedInstance()
NSNotificationCenter.defaultCenter().addObserver(self!, selector: "handleInterruption:", name: AVAudioSessionInterruptionNotification, object: nil)
audioSession.setActive(true, error: nil)
if (audioSession.setCategory(AVAudioSessionCategoryPlayback, error: &audioSessionError)) {
println("Successfully set the audio session")
} else {
println("Could not set the audio session")
}
let filePath = NSBundle.mainBundle().pathForResource("sound", ofType:"mp3")
let fileData = NSData(contentsOfFile: filePath!, options: .DataReadingMappedIfSafe, error: nil)
var error:NSError?
self!.audioPlayer = AVAudioPlayer(data: fileData, error: &error)
self!.audioPlayer?.numberOfLoops = -1
self!.audioPlayer?.delegate = self
if (self?.audioPlayer?.prepareToPlay() != false) {
println("Successfully prepared for playing")
} else {
println("Failed to prepare for playing")
}
})
然后在 didReceiveRemoteNotification
我试图在后台播放它:self.audioPlayer?.play()
,它 returns true
。可能它有效,但在大约 10 - 20 分钟后它不起作用。并注意 .play()
现在 returns false
.
禁用ARC(自动引用计数)以手动释放和释放
audioPlayer
是否有意义?也许我需要使用较低级别的 API,例如
OpenAL
?但是我不会使用它,因为它在 iOS 9 中已被弃用,以后我将需要在没有OpenAL
. 的情况下重写它
还有什么想法吗?也许我需要将
Audio Units
与RemoteIO
一起使用?如果可行,请提供一些示例。也许有像
ObjectAL
这样的第三方框架 -OpenAL
的简单实现。据我所知,它在 iOS 9. 中可用
这些方法只是我的假设。但他们的主要问题保持不变:这些方法会在后台运行吗?
您应该只禁用 ARC。当你进入背景时,如果你不使用它,它就会被释放。在 Swift 中创建 AVAudioPlayer 作为 Unmanaged<T>
对象。