在iOS中使用C函数中的ARC取消引用指针

问题描述:

我正在使用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); 
} 

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)你是路过的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通过让另一个所有者保持活动状态。

你可以告诉ARC存储的类型,你想:

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

只要确保在访问任何属性或调用任何方法之前做必要的零检查。