0

我有一个每次调用时都会播放声音的方法:

- (void)play :(NSString *) fileName : (NSString *) extension
{
    AUGraph theAUGraph;
    ...
    AUGraphStart(theAUGraph);
    ...
    [self performSelector:@selector(stopPlaying) withObject:theAUGraph afterDelay:5.0];
}

现在五秒钟后,选择器调用 stopPlaying 方法,并传递 AUGraph 对象:

-(void) stopPlaying: (AUGraph *) graph{
    AUGraphStop(graph);
}

我马上遇到的问题是:

Implicit conversion of C pointer type 'theAUGraph' (aka 'struct OpaqueAUGraph *') to Objective-C pointer type 'id' requires a bridged cast.

我尝试了两个建议的修复:

[self performSelector:@selector(stopPlaying) withObject:(__bridge id)(theAUGraph) afterDelay:5.0];

[self performSelector:@selector(stopPlaying) withObject:CFBridgingRelease(theAUGraph) afterDelay:5.0];

但是在运行时它只是因EXC_BAD_ACCESS而崩溃

我很困惑,那我该如何传递对象呢?

4

2 回答 2

2

AUGraph不是一个 Objective-C 对象。

你可以把它装箱NSValue,但我会简单地用调用来替换那行代码dispatch_after()(Xcode 有一个模板来展示如何使用dispatch_after)。

于 2013-06-09T21:04:38.407 回答
0

这是同一种结束方式的不同方式:

-(void)play :(NSString *) fileName : (NSString *) extension
{
    self.timer2 = nil;
    [self initializeTimer2];

    self.soundID = 0;
    NSString * soundFile = [[NSBundle mainBundle] pathForResource:fileName  ofType:extension];

           AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:soundFile], &soundID);

           AudioServicesPlaySystemSound(soundID);

           void * clientData = self;

          AudioServicesAddSystemSoundCompletion (soundID,
                                                 NULL,
                                                 NULL,
                                                 MyAudioServicesSystemSoundCompletionProc,
                                                 clientData);
   }


-(void) initializeTimer2
{
    // *********************************************************
    // Create Timer by this method to be able to stop it later
    // *********************************************************

    self.timer2 = [NSTimer timerWithTimeInterval:3.2 target:self selector:@selector(poll2:) userInfo:nil repeats:NO];
    [[NSRunLoop currentRunLoop] addTimer:self.timer2 forMode:NSDefaultRunLoopMode];

}

-(void) poll2:(NSTimer *) theTimer
{
    [self.timer2 invalidate];

    AudioServicesRemoveSystemSoundCompletion (self.soundID
                                                   );

    // *******************************************************************
    // Used if device is muted. Will cause the login to dismiss
    // *******************************************************************

    if ( self.commandAccessBool == YES)
    {
        [self.delegate didConfirmUserAccount];  
    }
    if ( self.editAccessBool == YES)
    {
        [self.delegate didConfirmUserAccountEditorLevel];  
    }

}

void MyAudioServicesSystemSoundCompletionProc (SystemSoundID  ssID,
                                               void * clientData)
{

    AudioServicesRemoveSystemSoundCompletion (ssID);


    //[((UserLoginViewController *)clientData).timer2 invalidate];

    // *******************************************************************
    // The class was passed as a void *
    // We have to cast it to the class and then call the delegate method
    // *******************************************************************

    if (((UserLoginViewController *)clientData) != nil)
    {
        if ( ((UserLoginViewController *)clientData).commandAccessBool == YES)
        {
            [((UserLoginViewController *)clientData).delegate didConfirmUserAccount];  
        }

        if ( ((UserLoginViewController *)clientData).editAccessBool == YES)
        {
            [((UserLoginViewController *)clientData).delegate didConfirmUserAccountEditorLevel];  
        }
    }

}
于 2013-06-09T21:17:23.727 回答