我有一个课程,我打电话来使用AVAudioPlayer
,在播放音频时一切正常和花花公子,但是当调用-audioPlayerDidFinishPlaying:
时我的NSLog()
命令说玩家被释放;问题是该应用程序稍后崩溃。我应该提到audioPlayer
是本课程中的一个ivar。这是代码:
-(id) initWithFileName:(NSString *)sndFileName
{
[super init];
sndFileToPlay = [[NSString alloc] initWithString:sndFileName];
return self;
}
-(void)dealloc {
[audioPlayer release];
self.audioPlayer.delegate = nil;
self.audioPlayer = nil;
[super dealloc];
}
-(void)play
{
[self playSound:sndFileToPlay];
}
-(void)playSound:(NSString *)fileName
{
NSString *fname, *ext;
NSRange range = [fileName rangeOfString:@"."];
int location = range.location;
if( location > 0 )
{
fname = [fileName substringWithRange:NSMakeRange(0, location)];
ext = [fileName substringFromIndex:location+1];
[self playSound:fname :ext];
}
}
-
-(void)playSound:(NSString *)fileName :(NSString *)fileExt
{
NSBundle *mainBundle = [NSBundle mainBundle];
NSURL *fileURL = [NSURL fileURLWithPath:
[mainBundle pathForResource:fileName ofType:fileExt] isDirectory:NO];
if (fileURL != nil)
{
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL
error: nil];
[fileURL release];
[audioPlayer setDelegate:self];
[audioPlayer play];
}
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player
successfully:(BOOL)flag
{
NSLog(@"Releasing");
[audioPlayer release];
}
答案 0 :(得分:4)
您的代码存在一些问题。
首先,在dealloc
:
[audioPlayer release];
self.audioPlayer.delegate = nil;
self.audioPlayer = nil;
您正在发布audioPlayer,然后,在发布的(可能已取消分配)播放器上,您将委托设置为nil,然后再将属性设置为再次释放。删除[audioPlayer release];
。
在你的audioPlayerDidFinishPlaying:successfully:
中你也发布了播放器,但你没有将变量设置为nil
。这可能会导致崩溃,因为再次访问此变量时,另一个对象可能位于该内存地址。请改用该属性,并按照dealloc
:
self.audioPlayer.delegate = nil;
self.audioPlayer = nil;
然后,在playSound::
(argh,非命名的第二个参数!)中,你过度释放fileURL
。 -[NSURL fileURLWithPath:isDirectory:]
返回一个自动释放的对象,你可能不会释放它。
最后但也许并非最不重要的是你泄漏sndFileToPlay
,你需要在你的dealloc
方法中发布它。而不是sndFileToPlay = [[NSString alloc] initWithString:sndFileName];
只需sndFileToPlay = [sndFileName copy];
。
您可能想要了解Objective-C内存管理。一旦你知道了三个或四个经验法则,这并不难。
答案 1 :(得分:0)
您应该清理代码。如果多次调用playSound,则会泄漏AVAudioPlayer。
在你的dealloc中,你应该将[audioPlayer release]放在下面的两行之后。
启用NSZombieEnabled进行调试,并确保在调用didFinish时不释放audioPlayer。