【发布时间】:2012-06-15 23:32:53
【问题描述】:
我在带有 ARC 的 iOS5 中使用 Blocks 来通过 AVAudioPlayer 播放一个永无止境的录音循环。我在收到 AVAudioPlayerDidFinishRecording 消息后分配了一个新的 AVAudioPlayer,它开始了一个递归循环。我的应用程序在播放 120 个左右的音频片段后总是崩溃。我可以看到,随着每个音频文件的加载,它会占用越来越多的内存,但永远不会释放内存。
我正在使用单个 AVAudioPlayer 属性,因此我希望 ARC 每次分配新播放器时都会清理旧实例。
这些块是否会以某种方式导致旧的 AVAudioPlayers 继续存在?
使用观察者监控玩家并启动/分配新玩家会更好吗?
非常感谢您的帮助!
-(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];
}
【问题讨论】:
-
如果您包含一些相关代码会更容易提供帮助。
-
使用嵌套块的一般规则:不要。单独的内存管理是可怕的。请改用 while 循环。
-
花时间创建一个SSCCE 可能会对您有所帮助;你可以自己解决这个问题。它肯定会让其他人更容易帮助你。
-
@JoshCaswell 感谢您的提示。下次发帖之前我会花时间做这件事。
-
是的,你只是在旧块中调用一个新块,还是
dispatch_async()-ing 到同一个队列?如果是前者,试试后者……
标签: objective-c ios ios5 automatic-ref-counting objective-c-blocks