1

我正在为 AVAudioPlayer 使用单例,效果很好。

我希望在初始化播放器之前添加一个检查,如果播放器已经在播放某些内容,则停止播放器。

我添加了这段代码:

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

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

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
4

1 回答 1

2

我不确定这是否是导致错误的原因,但我想我会在此处发布我对讨论的回复,以使我的观点更清楚,因为我将有更多的空间和代码格式。

不,您不必重写所有方法,我只是要求确保我理解一切正确。我说的另一部分是就像 in 一样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 的指针,同时创建一个播放器对象,因为它是一个单例。话虽如此,我不知道为什么这会导致它崩溃,而不是你“应该”使用 self 。


+ (SoundPlayer *)sharedInstance {
        if (sharedInstance == nil) {
            sharedInstance = [[super allocWithZone:NULL] init];
        }

        return sharedInstance;
    }

在这里看到AVAudioPlayer 只有 2 个init方法,而且都没有,init因此你没有完全初始化你的超类。您需要重写initWithContentsOfURL:url方法并使用 url 参数初始化此对象及其超级对象。只需确保将initWithContentsOfURL:url.h 和 .m 都放入。如果它很重要,也可以尝试,但alloc不要尝试allocWithZone

于 2012-07-16T01:22:10.067 回答