AVAudio播放器singleton在isPlaying检查时崩溃



我正在为AVAudioPlayer使用一个单例,它工作得很好。

我希望在初始化玩家之前添加一个复选框,如果玩家已经在玩什么,则停止它。

我添加了这个代码:

SoundPlayer *player = [SoundPlayer sharedInstance];
        if([player isPlaying]){
            [player stop];
 }

但它在if([player isPlaying])行上给了我一个EXE_BAD_ACCESS。

2个问题:

  1. 如果这是一个单身汉,而我又得到了同一个球员,那么为什么它不自己停下来呢
  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

最新更新