Swift:非托管 AVAudioPlayer

Swift: Unmanaged AVAudioPlayer

我有 AVAudioPlayer 个实例:

var audioPlayer: AVAudioPlayer!
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")
}

我需要为此 AVAudioPlayer 禁用 ARC。 Unmanaged 没有很好的文档记录,所以很难做到这一点。这是我尝试过的:

var audioPlayer: Unmanaged<AVAudioPlayer>!
//Stuck after creating nil instance, what to do now?
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")
}

你应该写:

// Properties in your class
var unmanagedAudioPlayer: Unmanaged<AVAudioPlayer>
var audioPlayer : AVAudioPlayer!

// code
self.audioPlayer = AVAudioPlayer(...)
self.unmanagedAudioPlayer = Unmanaged.passRetained(self.audioPlayer)

现在您可以像往常一样使用 self.audioPlayer 作为 AVAudioPlayer(如果您愿意,也可以使用 AVAudioPlayer!,但我不明白为什么)。

self.unmanagedAudioPlayer 保留对 self.audioPlayer 的保留引用,这样它就不能被 ARC 释放。

当你用完这个AVAudioPlayer对象后,你可以调用self.unmanagedAudioPlayer.release()(或autorelease)来释放它,就像你在Objective-C中做的一样.

实际上您不需要单独存储 self.audioPlayer,因为您始终可以通过 unmanagedAudioPlayer.takeUnratainedValue() 获取它,但它是使您的代码更具可读性的好别名。

这不是问题。 "turn off ARC" 的建议是错误的,您不应该尝试这样做。如果你有内存问题,你应该直接解决它。例如,如果后台的 AVAudioPlayer 有问题,请在进入后台时将其设置为 nil,以将其从内存中释放。但更重要的是,您应该问自己为什么会遇到这个问题。多年来我一直在使用 AVAudioPlayer,我从来没有遇到过 "it leaks from memory"(不管你是什么意思)的情况。