views:

330

answers:

2

I have a thing that uses a SystemSoundID to play a sound, and then repeat with a C function being used as the sound completion callback, and the function is passed (void *)self (since it has to be a void pointer), and then I want to play the sound again if the alarmPlaying BOOL ivar of self is true, otherwise remove the sound completion and dispose the SSID (providing an instance method to set alarmPlaying to NO). What it the proper way to take self in the form of a void pointer and get its alarmPlaying ivar? There's no point in using a property if I don't need to. I keep getting the error Request for member 'alarmPlaying' in something not a structure or union, and a dereferencing void pointer warning. Here's the function I have:

static void alarmSoundDidComplete(SystemSoundID soundID, void *myself) {
    // ******* How do I access alarmPlaying from a 'self' casted to a void * ? *******
    if((MidnightViewController *)myself->alarmPlaying) {
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     [NSThread sleepForTimeInterval:kAlarmBeepInterval];
     AudioServicesPlaySystemSound(soundID);
    } else {
     AudioServicesRemoveSystemSoundCompletion(soundID);
     AudioServicesDisposeSystemSoundID(soundID);
    }
}

(Its running on its own thread, so I have a kAlarmBeepInterval #define'd)

and in the implementation of the class I have:

- (void)startPlayingAlarm {
    SystemSoundID alarmSoundID = [Utilities createSystemSoundIDFromFile:@"beep"
                                                                 ofType:@"caf"];
    AudioServicesAddSystemSoundCompletion(alarmSoundID, NULL, NULL,
               alarmSoundDidComplete, (void *)self);
    alarmPlaying = YES;
    AudioServicesPlaySystemSound(alarmSoundID);
}

- (void)stopPlayingAlarmAndDisposeSystemSoundID {
    alarmPlaying = NO;
}

Thanks.

+1  A: 

-> has higher precedence than the cast; you need to do this:

if(((MidnightViewController *)myself)->alarmPlaying) {
newacct
You were right! Unfortunately, I realized the other answer is right too, now I get a warning saying that its @protected and I will get a hard error in the future. Should I just use an accessor, or make it @public? This will get called about every half second or so.
Mk12
+1  A: 

I believe the proper way would be to create a property (sorry), because encapsulation is the object oriented way. To not get the error and do what you're trying to do you need to make the ivar public using @public in the interface. By default, all ivars are protected.

Cory Kilger