iPhone: управление памятью AVAudioPlayer / NSURL - PullRequest
0 голосов
/ 05 февраля 2010

Я опубликовал гораздо более длинный вопрос несколько минут назад, и, как правило, сразу после его публикации я понял, что происходит, поэтому я удалил его, так как большая часть сообщения была неактуальной. Затем я вернулся в Google.

Оказывается, у меня почти та же самая проблема, которая описана в этом посте, без ответа с июня. http://www.iphonedevsdk.com/forum/iphone-sdk-development/20975-avaudioplayer-nsurl-memory-management.html

В итоге: я использую AVAudioPlayer и освобождаю его с помощью audioPlayerDidFinishPlaying: успешно: метод делегата. После того, как я инициализирую проигрыватель, связанный с ним объект NSURL должен быть освобожден, иначе он протекает. Но когда я отпускаю его после инициализации плеера, он падает, так как он уже освобожден. Странно то, что он не всегда падает в первый раз, в большинстве случаев он падает после воспроизведения второго звука. Иногда (редко) это позволяет распределять / освобождать несколько игроков (я снова использую указатели после освобождения) перед сбоем. Любая помощь?

Фрагмент кода: (soundKeyUp - переменная класса AVAudioPlayer *, следовательно, здесь нет объявления)

NSString *soundKeyUpPath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"soundKeyUp%d", key.tag % 5] ofType:@"wav"];
    NSURL *soundKeyUpURL = [[NSURL alloc] initFileURLWithPath:soundKeyUpPath];
    soundKeyUp = [[AVAudioPlayer alloc] initWithContentsOfURL:soundKeyUpURL error:nil];
    if(soundKeyUp) {
        [soundKeyUp setDelegate:self];
        [soundKeyUp play];
    }
    else {
        [soundKeyUp release];
        soundKeyUp = nil;
    }

    [soundKeyUpPath release];
    [soundKeyUpURL release];

Ответ Стиву Риггинсу: Хитрость в том, что он не падает каждый раз в одно и то же время, как уже упоминалось. Он почти всегда правильно выпускается в первый раз (или, по крайней мере, он не падает или не просачивается), но обычно после второго раза, когда я выделяю / освобождаю плеер и URL, происходит сбой при освобождении URL. Иногда перед сбоем проходит 3, 4, 5+ раз, но это всегда так.

Ответы [ 2 ]

1 голос
/ 05 февраля 2010

Отпустите URL при создании проигрывателя. Я делаю это в моем приложении, и он работает нормально. Нет утечек, сбоев и т. Д.

AVAudioPlayer *newPlayer =
        [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL
                                               error: nil];
        [fileURL release];

И никогда, никогда не выпускайте объекты, которые содержатся в других объектах. Это их работа, а не ваша.

Редактировать: Если ваш URL все еще течет, вам нужно посмотреть, что вы делаете, когда создаете его. Это должно быть что-то вроде:

NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: [self path]];

Следуя правилам владения Cocoa, использование метода alloc означает, что вы владеете им, поэтому вы его освобождаете.

0 голосов
/ 05 февраля 2010
 - (IBAction) playaction {

        NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:@"songname" ofType:@"mp3"];
        NSURL *newURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
        self.soundFileURL = newURL;
        [newURL release];
        [[AVAudioSession sharedInstance] setDelegate: self];
        [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryAmbient error: nil];

    // Registers the audio route change listener callback function
    AudioSessionAddPropertyListener (
                                     kAudioSessionProperty_AudioRouteChange,
                                     audioRouteChangeListenerCallback,
                                     self
                                     );

    // Activates the audio session.

    NSError *activationError = nil;
    [[AVAudioSession sharedInstance] setActive: YES error: &activationError];

    AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: soundFileURL error: nil];
    self.appSoundPlayer = newPlayer;
    [newPlayer release];
    [appSoundPlayer prepareToPlay];
    [appSoundPlayer setVolume: 1.0];
    [appSoundPlayer setDelegate: self];
    [appSoundPlayer play];

}

Вы должны будете использовать что-то похожее на это. Здесь appSoundPlayer объявлен в заголовочном файле как

AVAudioPlayer *appSoundPlayer;

Также установите для него свойство,

@property(nonatomic, retain)AVAudioPlayer *appSoundPlayer;

Отпустите его в методе dealloc. Я придерживаюсь этого метода и не обнаружил утечек памяти

...