0

AVAudioPlayer で終わりのないオーディオ録音サイクルを再生するために、ARC で iOS5 のブロックを使用しています。再帰のサイクルを開始する AVAudioPlayerDidFinishRecording メッセージを受信した後、新しい AVAudioPlayer を割り当てます。120 程度のオーディオ クリップが再生されると、アプリが頻繁にクラッシュします。各オーディオ ファイルが読み込まれるたびにメモリを消費していることがわかりますが、メモリが解放されることはありません。

私は単一の AVAudioPlayer プロパティを使用しているので、新しいプレーヤーを割り当てるたびに ARC が古いインスタンスをクリーンアップすることを期待していました。

  1. ブロックが原因で、古い AVAudioPlayers が残っている可能性はありますか?

  2. オブザーバーを使用してプレーヤーを監視し、新しいプレーヤーを起動/割り当てたほうがよいでしょうか?

助けてくれてどうもありがとう!

-(void)playNextAudioItem{
    //get ready to load audio doc from iCloud
    NSURL *ubiquitousContainer = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
    if(ubiquitousContainer){
        //query iCloud
        query = [[NSMetadataQuery alloc]init];
        [query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
        NSPredicate *pred = [NSPredicate predicateWithFormat:@"(%K == %@)", NSMetadataItemFSNameKey, [NSString stringWithFormat:@"%@.caf", audioItemGUID]];
        [query setPredicate:pred];
        [[NSNotificationCenter defaultCenter] addObserverForName:NSMetadataQueryDidFinishGatheringNotification object:query queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif){
            //iCloud query finished gathering data
            [query disableUpdates];
            [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query];
            NSMetadataItem *item1 = [query resultAtIndex:0];
            audioCurrentVerse = [[audioDoc alloc] initWithFileURL:[item1 valueForAttribute:NSMetadataItemURLKey]];
            //open the audio file
            [audioCurrentVerse openWithCompletionHandler:^(BOOL success) {
                if(success){
                    //configure the session and play the audio file
                    AVAudioSession *audioSession = [AVAudioSession sharedInstance];        
                    [audioSession setActive:YES error:nil];
                    NSError *error = nil;
                    [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
                    audioPlayer = [[AVAudioPlayer alloc] initWithData:audioCurrentVerse.data error:&error];
                    audioPlayer.numberOfLoops = 0;
                    audioPlayer.delegate = self;
                    if([audioPlayer prepareToPlay]){
                        [audioPlayer play];
                    }
                }
            }];
            [query stopQuery];
            query = nil;
        }];
        [query startQuery];
    }
}

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
    //get an identifier for the next audio item
    audioItemIndex++;
    if(audioItemIndex >= rsAudioItems.recordCount){
        verseIndex = 0;
    }
    audioItemGUID = [rsAudioItems getRow:audioItemIndex andColumnNamed:@"audioItemGUID"];
    //recursive call to play the next audio item
    NSLog([NSString stringWithFormat:@"%d", playCount++]);
    [self playNextAudioItem];
}
4

1 に答える 1

1

ブロックは、ブロックが解放されるまで解放されないスタックのスナップショットを取得します。ブロックは決して解放されないため、スナップショットは永久に残ります。

for ループを使用すると、この問題が軽減されます。それらをシリアルディスパッチキューに追加すると、実行後に解放されます。

于 2012-06-13T05:11:31.577 に答える