2012-01-30 42 views
5

我希望標題是不是太誤導... :)AudioServicesAddSystemSoundCompletion使用__bridge

我玩了系統的聲音,並添加SoundCompletion回調到它像這樣:

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

而«自»是一個簡單的NSObject的

在完成回調我嘗試再次調用播放程序:

我不得不添加的__bridge_transfer和_ _bridge_retained到強制轉換,否則我會遇到錯誤,崩潰或其他意外行爲。

但是,儘管如此,整個事情並不奏效。

我存儲的聲音在NSMutableArray中播放,抓住數組的第一個條目並播放它,添加聲音完成並希望發生事情。 但是 - 與所有的留存轉移的東西,在NSMutableArray中是在第二次調用空...

下面的代碼:

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); 
    } 
} 

[編輯] - 回答我的問題:

總是很高興自己找到它:)

原來,我幾乎在那裏。

設置回調調用如下:

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

然後,在回調函數,我這樣做:

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

和它的作品...

+0

感謝您的回答,真的幫了我大忙!雖然幾乎錯過了,因爲問題似乎沒有答案 - 你允許爲自己的問題添加一個答案嗎?或者我可以添加它指向您的意見?乾杯v反正;] – davidfrancis 2012-03-15 11:18:31

回答

8

我無法回答我自己的問題,因爲我對StackOverflow太快 - 所以只是爲了使這個完成,我再次添加答案:)

原來,我幾乎在那裏。

設置回調調用如下:

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

然後,在回調函數,我這樣做:

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

和它的作品...

+0

是否有一個原因,你不能只使用__bridge?使用此方法後,我得到崩潰訪問對象。 – 2013-03-12 18:20:10

+0

適用於我。 @AlastairStuart我認爲這一點是當你傳遞對象到'AudioServicesAddSystemSoundCompletion'時,你做了__bridge_retained,這將增加retainCount 1. __bridge保證沒有所有權轉移,所以計數器在回調中保持不變。然後CFRelease會將retainCount減1並最終刪除對象。 – Andy 2014-06-20 22:50:42

+0

CFRelease不是在'theClass'而是在'我自己'? – shim 2015-11-02 03:54:41

4

對於任何需要一點額外幫助的人... 我得到了Swissdude的答案,在普通視圖控制器中工作,例如:

注:(不能使用CFRelease(我自己))

.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... 
相關問題