AVAudioPlayer предустановил утечку звука из памяти

У меня есть экземпляр 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(), он возвращает true. Наверное, это работает, но примерно через 10-20 минут это не сработает. И обратите внимание, что .play() теперь возвращает false.

  • Есть ли смысл отключить ARC (автоматический подсчет ссылок) для освобождения и dealloc audioPlayer вручную?

  • Возможно, мне нужно использовать API более низкого уровня, например OpenAL? Однако я не буду использовать его, поскольку он устарел в iOS 9 и позже мне нужно будет переписать его без OpenAL.

  • Есть идеи? Может быть, мне нужно использовать Audio Units с RemoteIO? Если это сработает, укажите несколько примеров.

  • Возможно, существуют сторонние структуры, такие как ObjectAL - простая реализация OpenAL. Как я знаю, он доступен в iOS 9.

Эти методы - только мои предположения. Но главный вопрос остается тем же: Будут ли эти методы работать из фона?

Ответ 1

Вы должны просто отключить ARC. Когда вы вводите backgroud, тогда, если вы его не используете, он освобождается. В Swift создайте AVAudioPlayer как объект Unmanaged<T>.