2012-01-30 14 views
5

Mam nadzieję, że tytuł nie jest zbyt mylące ... :)AudioServicesAddSystemSoundCompletion pod ARC użyciu __bridge

Gram dźwięk systemu i dodać SoundCompletion-oddzwanianie do niego tak:

AudioServicesAddSystemSoundCompletion(soundID, NULL, NULL, completionCallback, (__bridge_retained void *)self); 

Zważywszy « własny »jest prosty NSObject

W zwrotnego zakończenia próby wywołania rutynowe gra znowu:

musiałem dodać __bridge_transfer i tym _ _bridge_retained do rzutów, w przeciwnym razie dostanę błędy, awarie lub inne nieoczekiwane zachowanie.

Ale cała rzecz nie działa mimo wszystko.

przechowywać dźwięki grać w NSMutableArray, chwyć pierwszy wpis tablicy i odtworzyć go, dodać na zakończenie dźwięku i nadzieję rzeczy się dzieje. Ale - ze wszystkim, co dotyczy zachowanie przeniesienie rzeczy, NSMutableArray jest pusta na drugie wezwanie ...

Oto kod:

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

    NSLog(@"Audio callback"); 

    AudioServicesRemoveSystemSoundCompletion (mySSID); 
    AudioServicesDisposeSystemSoundID(mySSID); 

    [(__bridge_transfer Speaker *)myself speakCharacter]; 

    CFRelease(myself); // I heard I need this? 

} 

-(void)speakCharacter{ 

    if([sounds count] > 0){ 

     NSString *soundToPlay = [sounds objectAtIndex:0]; 
     [sounds removeObjectAtIndex:0]; 
     NSLog(@"TxtToSpeak %@", soundToPlay); 
     CFURLRef  soundFileURLRef; 
     NSURL *path = [[NSBundle mainBundle] URLForResource:[soundToPlay uppercaseString] withExtension:@"aif"]; 
     soundFileURLRef = (__bridge CFURLRef)path; 
     SystemSoundID soundID; 
     AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID); 
     AudioServicesAddSystemSoundCompletion(soundID, NULL, NULL, completionCallback, (__bridge_retained void *)self); 
     AudioServicesPlaySystemSound (soundID); 
    } 
} 

[EDIT] - odpowiedzi na moje własne pytanie:

zawsze miło się tego dowiedzieć się :)

Okazuje się, byłem prawie na miejscu.

Wezwanie do konfigurowania zwrotnego jest następujący:

AudioServicesAddSystemSoundCompletion(soundID, NULL, NULL, completionCallback, (__bridge_retained void *)self); 

Następnie w Callback-funkcji, to zrobić:

myClass *theClass = (__bridge myClass *)myself; 
    CFRelease(myself); 
    [theClass playNextSound]; // The routine that plays the sounds 

I to działa ...

+0

Dzięki za odpowiedź naprawdę mi pomogłem! Prawie jednak przeoczyłem, ponieważ pytanie wydaje się bez odpowiedzi - czy możesz dodać odpowiedź na własne pytanie? Czy mogę dodać to wskazując na twoje komentarze? Pozdrawiam V wiele razy;] – davidfrancis

Odpowiedz

8

nie mogę odpowiedzieć na moje własne pytanie, ponieważ byłem zbyt szybki dla StackOverflow - tak właśnie zrobić to kompletny, znowu dodać odpowiedź :)

Okazało się, byłem już prawie na miejscu.

Wezwanie do konfigurowania zwrotnego jest następujący:

AudioServicesAddSystemSoundCompletion(soundID, NULL, NULL, completionCallback, (__bridge_retained void *)self); 

Następnie w Callback-funkcji, to zrobić:

myClass *theClass = (__bridge myClass *)myself; 
CFRelease(myself); 
[theClass playNextSound]; // The routine that plays the sounds 

I to działa ...

+0

Czy jest jakiś powód, dla którego nie można po prostu użyć __bridge? Po tej metodzie otrzymuję awarie dostępu do obiektu. –

+0

Działa dla mnie. @AlastairStuart Myślę, że chodzi o to, kiedy przekazujesz obiekt do 'AudioServicesAddSystemSoundCompletion', który robisz __bridge_retained, który zwiększy wartość retainCount o 1. __bridge gwarantuje brak transferu własności, więc licznik pozostanie taki sam w wywołaniu zwrotnym. CFRelease następnie zmniejszy retainCount o 1 i ostatecznie usunie obiekt. – Andy

+0

Czy CFRelease nie byłby na "klasie" w przeciwieństwie do "siebie"? – shim

4

dla każdego, który potrzebuje trochę dodatkowej pomocy ... dostałem odpowiedź Swissdude do pracy we wspólnym kontrolera widoku jako takie:

uwaga: (nie można używać CFRelease (siebie))

.h

#import <UIKit/UIKit.h> 
#import <AudioToolbox/AudioToolbox.h> 

@interface MYVIEWCONTROLLERNAME : UIViewController 

@property SystemSoundID mySentenceAudio; 

@end 

.m

#import "MYVIEWCONTROLLERNAME.h" 

@interface MYVIEWCONTROLLERNAME() 
{ 
    int myLetterCount; 
    int myWordLength; 
} 
@end 

@implementation MYVIEWCONTROLLERNAME 

@synthesize mySentenceAudio; 


    #pragma mark - Click Action 

- (IBAction)SpellButtonPress:(UIButton *)sender { 
    [self AudioDataAndPlayerLoader]; 
    myLetterCount = 0; 
} 

# pragma mark - Audio Data 

-(void) AudioDataAndPlayerLoader { 

    NSString*myWord = @"apple"; 
    myWordLength = myWord.length; 
    NSArray*wordArray= [self stringToLetterArray:myWord]; 

    if (myWordLength > myLetterCount) { 
     NSString* myLetter = [wordArray objectAtIndex:myLetterCount]; 
     [self playMySound:myLetter]; 
    } 
} 

- (NSArray*)stringToLetterArray:(NSString*)string { 
    NSUInteger characterCount = [string length]; 
    NSMutableArray *temparray = [NSMutableArray arrayWithCapacity:[string length]]; 
    for (int i = 0; i<characterCount; i++) 
    { 
     [temparray addObject:[string substringWithRange:NSMakeRange (i,1)]]; 
    } 
    return [temparray copy]; 
} 

#pragma mark - Audio Loop 

- (void) myAudioLoopCheck { 
    myLetterCount++; 
    NSLog(@"Audio Looped"); 
    if (myWordLength > myLetterCount) { 
     [self performSelector:@selector(AudioDataAndPlayerLoader) withObject:nil afterDelay:.2]; 
    } 
    else { 
     NSLog(@"Done"); 
     myLetterCount = 0; 
    } 
} 

#pragma mark - Audio Player 

- (void) playMySound: (NSString*)soundTitle{ 

    NSString* SOUNDPATH = [[NSBundle mainBundle] 
          pathForResource:soundTitle 
          ofType:@"m4a" 
          inDirectory:@"audio/abc/"]; 
    if (SOUNDPATH != nil) { 

     CFURLRef baseURL = (__bridge_retained CFURLRef) [[NSURL alloc] initFileURLWithPath:SOUNDPATH]; 
     AudioServicesCreateSystemSoundID (baseURL, &mySentenceAudio); 

     AudioServicesPlaySystemSound(mySentenceAudio); 
     CFRelease(baseURL); 

     AudioServicesAddSystemSoundCompletion (mySentenceAudio,NULL,NULL,theAudioServicesSystemSoundCompletionProc,(__bridge void*)self); 
    } 
    else { 
    } 
} 

#pragma mark - Audio Player Callback 

static void theAudioServicesSystemSoundCompletionProc (SystemSoundID mySentenceAudio, void *myself) { 
    NSLog(@"Audio callback"); 
    AudioServicesRemoveSystemSoundCompletion (mySentenceAudio); 
    AudioServicesDisposeSystemSoundID(mySentenceAudio); 

    MYVIEWCONTROLLERNAME *theClass = (__bridge MYVIEWCONTROLLERNAME *)myself; 
    [theClass myAudioLoopCheck]; 
} 

// life cycle code... 
Powiązane problemy