PictureMeAndYou
PictureMeAndYou

Reputation: 533

changing a variable in completionblock

Hello I am currently having issues bridging a variable in my completion block. I want to set isPreviewPlaying to NO in the completion block but I can't.

static void completionCallback (SystemSoundID  mySSID, void *myself) {


  AudioServicesRemoveSystemSoundCompletion (mySSID);
  AudioServicesDisposeSystemSoundID(mySSID);

  CFRelease(myself); 
  UIButton *previewButton = (__bridge UIButton*)myself;
  [previewButton setTitle:@"Preview" forState:UIControlStateNormal];
  _isPreviewPlaying = NO // I want to do this, but I can't.
}

- (void)previewButtonPressed:(id)sender {
 if (_isPreviewPlaying) {
   _isPreviewPlaying = NO;
   NSLog(@"STOP");
   AudioServicesDisposeSystemSoundID(soundID);
 } else {
   NSString * selectedPreviewSound = [self.soundFile objectAtIndex: _soundFileIndex];
   AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath: selectedPreviewSound], &soundID);
   AudioServicesPlaySystemSound (soundID);
   _isPreviewPlaying = YES;
   AudioServicesAddSystemSoundCompletion(soundID, NULL, NULL, completionCallback, (__bridge_retained void *)sender);
   [sender setTitle:@"Stop" forState:UIControlStateNormal];
 }
}

Upvotes: 0

Views: 58

Answers (1)

Droppy
Droppy

Reputation: 9721

You will need to pass the class instance to the completion block function, as it's a C function, and that way you can access properties and methods on the instance.

That is the intent of myself parameter I believe, however you are currently releasing it using CFRelease() for some reason I cannot fathom (I am assuming that sender is a button as previewButtonPressed: looks like a button event callback, and releasing it won't do it any favours; read crash).

Therefore I would suggest:

  1. Remove the CFRelease() call.
  2. Cast myself to whatever the class is: MyClass *myclass = (MyClass *)myself;.
  3. Call myclass.previewPlaying = NO; (assuming it's a property). Call [myclass previewNotPlaying] (see below).
  4. Pass self instead of sender to AudioServicesAddSystemSoundCompletion().

EDIT Having said that, I now see you are using the button instance to display information. Instead of calling the property, above, call a method on the instance instead and make that method do the work:

- (void)previewNotPlaying
{
    // _previewButton is an IBOutlet to the button
    [_previewButton setTitle:@"Preview" forState:UIControlStateNormal];
    _isPreviewPlaying = NO;
}

Upvotes: 1

Related Questions