2013-07-18 18 views
4

我正在使用The Amazing Audio Engine來處理在iOS應用程序中同步的回放。在iOS中使用C函數中的ARC取消引用指針

該框架要求您使用C函數作爲在音頻線程上調用的回調函數(playbackTimingReceiver)。然後您需要使用傳遞處理程序(pageTurnHandler)的C函數(AEAudioControllerSendAsynchronousMessageToMainThread)再次向主線程發送消息。

我沒有過多的C語言工作經驗,但據我所知,我在需要解除引用的消息中傳遞一個指針。

,我可以用線順利實現:

PlaybackManager* receiver = *((PlaybackManager**)userInfo); 

但是,只有當我把ARC關閉該項目使用了-fno-objc弧標誌的項目目標編譯源該文件。

對我的問題,是否有可能實現這與ARC打開?如果是的話,什麼是正確的語法?

相關代碼段:

#pragma mark - Audio Timing Callback 
-(AEAudioControllerTimingCallback)timingReceiverCallback 
{ 
    return playbackTimingReceiver; 
} 

static void playbackTimingReceiver(PlaybackManager* receiver, 
            AEAudioController *audioController, 
            const AudioTimeStamp *time, 
            UInt32 const frames, 
            AEAudioTimingContext context) 
{ 
    receiver->_hostTime = getUptimeInMilliseconds(time->mHostTime); 
    AEAudioControllerSendAsynchronousMessageToMainThread(audioController, 
                 pageTurnHandler, 
                 &audioController, 
                 sizeof(id)); 
} 

static void pageTurnHandler(AEAudioController *audioController, void *userInfo, int userInfoLength) 
{ 
    PlaybackManager* receiver = *((PlaybackManager**)userInfo); 
    NSLog(@"Receiver:%@", receiver); 
} 

回答

2
PlaybackManager * receiver = (__bridge_transfer id)*(void **)userInfo; 

應該做的伎倆。這首先將userInfo轉換爲指針指針,因爲它包含原始對象指針的地址。取消引用以獲取原始指針,並使用__bridge_transferidPlaybackManager類型的工作 - 告訴ARC,取消引用的值實際上是一個需要照顧的對象。

+0

如何解引用void指針? –

+0

它不是取消引用無效指針,而是取消引用指針指針。 'void **' –

+1

謝謝你...停止了編譯器的抱怨,但是在運行時我得到了錯誤的訪問:線程1:EXE_BAD_ACCESS(code = 1,address = 0x30000008) – Brendt

1

沒有運行的代碼,似乎有兩個錯誤:

1)你是路過的audioController內容時,它看起來像你的意思的receiver內容傳遞 - 所以最後兩個參數傳遞給AEAudioControllerSendAsynchronousMessageToMainThread應該&receiver & sizeof(PlaykbackManager *)

2)你需要一個橋樑投來獲取對象引用背出

喜歡的東西:

static void playbackTimingReceiver(PlaybackManager* receiver, 
            AEAudioController *audioController, 
            const AudioTimeStamp *time, 
            UInt32 const frames, 
            AEAudioTimingContext context) 
{ 
    receiver->_hostTime = getUptimeInMilliseconds(time->mHostTime); 
    AEAudioControllerSendAsynchronousMessageToMainThread(audioController, 
                 pageTurnHandler, 
                 &receiver, 
                 sizeof(PlaybackManager*)); 
} 

static void pageTurnHandler(AEAudioController *audioController, void *userInfo, int userInfoLength) 
{ 
    PlaybackManager* receiver = (__bridge Playback *)*((PlaybackManager**)userInfo); 
    NSLog(@"Receiver:%@", receiver); 
} 

注意:將ARC控件世界中的對象引用傳遞到C世界時,您經常會轉移所有權 - 因此ARC不會釋放引用的對象 - 並在返回時將所有權轉移回來 - 所以ARC恢復所有權管理。但由於AEAudioControllerSendAsynchronousMessageToMainThread的性質,其中userInfo通過地址傳遞並在內部複製 - 因此是大小參數,所以轉移所有權更爲經濟。因此上面的代碼沒有。這意味着你必須確保任何對象receiver通過讓另一個所有者保持活動狀態。

0

你可以告訴ARC存儲的類型,你想:

PlaybackManager *audioBufferPlayer = *(__weak PlaybackManager **)userInfo;

只要確保在訪問任何屬性或調用任何方法之前做必要的零檢查。