我正在为AVAudioPlayer使用一个单例,它工作得很好。
我希望在初始化玩家之前添加一个复选框,如果玩家已经在玩什么,则停止它。
我添加了这个代码:
SoundPlayer *player = [SoundPlayer sharedInstance];
if([player isPlaying]){
[player stop];
}
但它在if([player isPlaying])
行上给了我一个EXE_BAD_ACCESS。
2个问题:
- 如果这是一个单身汉,而我又得到了同一个球员,那么为什么它不自己停下来呢
- 为什么我会出错
这是完整的代码
#import "SoundPlayer.h"
@implementation SoundPlayer
@synthesize helpMode;
static SoundPlayer *sharedInstance = nil;
+ (SoundPlayer *)sharedInstance {
if (sharedInstance == nil) {
sharedInstance = [[super allocWithZone:NULL] init];
}
return sharedInstance;
}
+(BOOL)playSound:(NSURL*)url{
NSError *error;
SoundPlayer *player = [SoundPlayer sharedInstance];
if([player isPlaying]){
[player stop];
}
player = [[SoundPlayer sharedInstance] initWithContentsOfURL:url error:&error];
[player play];
if (player == nil){
NSLog(@"error %@ n for file %@",[error description],[url path]);
return NO;
}else {
if (![player helpMode]) {
[player play];
}else{
NSLog(@"help mode");
}
}
return YES;
}
-(void)stopSound{
if ([self isPlaying]) {
[self stop];
}
}
@end
我不确定这是否是导致错误的原因,但我想我会在这里发布我对讨论的回应,以使我的观点更加清晰,因为我有更多的空间和代码格式。
不,你不必推翻所有的方法,我只是要求确保我理解所有正确的方法。我要说的另一点是,就像在stopSound{}
中一样,你应该使用self而不是
SoundPlayer *player = [SoundPlayer sharedInstance];
所以把你的代码改成这样,运行它,看看它是否修复了,在下面发表评论,让我知道结果。
-(BOOL)playSound:(NSURL*)url{
NSError *error;
// SoundPlayer *player = [SoundPlayer sharedInstance];
if([self isPlaying]){
[self stop];
}
//not sure if this should be self or super (i think super, try both)
//if you overrided the init then definitely self
//[self initWithContentsOfURL:url error:&error];
[super initWithContentsOfURL:url error:&error];
[self play];
if (self == nil){
NSLog(@"error %@ n for file %@",[error description],[url path]);
return NO;
}else {
if (![self helpMode]) {
[self play];
}else{
NSLog(@"help mode");
}
}
return YES;
}
实际上,你所做的就是创建一个指向self的指针,同时创建一个播放器对象,因为它是一个singleton。话虽如此,我不确定为什么这会让它崩溃,除了你"应该"使用自我这一事实。
+ (SoundPlayer *)sharedInstance {
if (sharedInstance == nil) {
sharedInstance = [[super allocWithZone:NULL] init];
}
return sharedInstance;
}
请看这里,AVAudioPlayer只有两个init
方法,两者都不是init
,因此您没有完全初始化您的超级类。您需要重写initWithContentsOfURL:url
方法,并使用url参数初始化此对象及其超级对象。只需确保将initWithContentsOfURL:url
同时放在.h和.m中即可。如果很重要,也可以使用idk,但只尝试alloc
而不是allocWithZone
。