ARC,块和C之间的回调

时间:2015-09-07 15:15:33

标签: objective-c c

我有一个c函数,它将回调函数作为一个参数,我将把一个Obj-C包装器写入标准的C API。我想用块替换C回调。

让我们设想一个C API:

void audioStopFunction(void (*callback)(void *), void *udata);

Obj-C包装器如下所示:

- (void)myAudioStopFunction:(dispatch_block_t)block
{
    void *udata = (__bridge void *)block;
    audioStopFunction(my_callback, udata);
}

void my_callback(void *udata)
{
    dispatch_block_t block = (__bridge_transfer dispatch_block_t)udata;
    block();
}

现在,我有一些问题:

  1. myAudioStopFunction函数中,我是否需要复制以下块:

      

    void * udata =(__ bridge void *)[block copy];

  2. my_callback函数中,我应该使用__bridge代替__bridge_transfer吗?此外,我是否需要在Block_release之后致电block()

  3. 代码是否会导致内存泄漏?如果有,那么正确的方法是什么?

1 个答案:

答案 0 :(得分:1)

由于C回调由包装器类管理,因此最容易让类管理块的所有权。 (我正在调用块completionBlock,因为这似乎更符合Cocoa命名约定。)

@interface AudioCallbackWrapper
@property (nonatomic) dispatch_block_t completionBlock;
@end

static void my_callback(void *udata)
{
    dispatch_block_t block = (__bridge dispatch_block_t)udata;
    if (block != nil)
        block();
}

@implementation AudioCallbackWrapper
- (void)setCompletionBlock:(dispatch_block_t)completionBlock
{
    _completionBlock = [completionBlock copy];
    audioStopFunction(my_callback, (__bridge void *)_completionBlock);
}
- (void)dealloc
{
    // remove the C callback before completionBlock is released
    self.completionBlock = nil;
}
@end

由于块的生命周期由封闭的包装器管理,因此C代码永远不必转移所有权。因此,代码仅包含__bridge的{​​{1}}强制转换。

  

代码是否会导致内存泄漏?如果是,那么正确的方法是什么?

每次回调触发时,您的原始代码都会释放该块。第一次回调后,块指针将悬空。