Ran*_*ook 8 objective-c callback ios automatic-ref-counting
我正在使用第三方库,需要在iOS程序中进行C回调.回调提供了一个void*我可以随意使用的userdata参数.在这个回调中,我想创建一个NSData对象,该对象返回到调用最终调用回调的API的代码.例如:
// C callback:
static void callback(int x, void* userdata)
{
if (userdata)
{
// This gives an error:
// Pointer to non-const type 'NSData*' with no explicit ownership
NSData** p = (NSData**)userdata;
*p = [NSData init:...];
}
}
// main code:
NSData* d = ...; // sometimes valid, sometimes nil
library_api(callback, &d); // have the callback initialize or replace d
if (d)
{
[d doSomthing:...];
}
Run Code Online (Sandbox Code Playgroud)
我正在使用ARC,我认为这是问题的根源.我想过使用一个结构来保存NSData*,但ARC禁止在结构或联合中使用Objective-C对象.可能有一些变体__bridge可能有所帮助,但我不确定哪个.我已经查看了很多SO问题并阅读了Apple文档,但我不清楚如何对其进行编码.
理想情况下,如果在调用回调时d不是nil,则会释放其当前值,并且新的NSData对象将替换它.换句话说,当library_api完成时,d总是保存由回调创建的NSData对象,并且任何先前保持的值都将被正确释放.
我想我可以将Objective-C代码保留在回调之外,只是malloc()一个缓冲区来存储数据,然后将其复制到主代码中的NSData对象,但我希望我能避免这一额外的步骤.
您无法将对象所有权转移到 a void*,但可以将对象所有权转移到 CoreFoundation 类型,例如CFDataRef或CFTypeRef。然后您就可以随意传递 CF 指针。
例如:
NSData* data = ...
CFTypeRef cfData = (__bridge CFTypeRef)data; // If you want to pass in data as well.
library_api(callback, &cfData);
if (cfData)
{
data = (__bridge_transfer NSData*)cfData; // Transfer ownership to ARC. No need to call CFRelease(cfData).
NSLog@("Data: %@", data);
}
Run Code Online (Sandbox Code Playgroud)
并在回调中:
static void callback(int x, void* userdata)
{
if (userdata)
{
CFTypeRef* cfDataPtr = userdata;
CFTypeRef cfInData = *cfDataPtr;
NSData* inData = (__bridge NSData*)cfInData;
NSLog(@"In Data: %@", inData);
NSData* outData = [[NSData alloc] init];
CFTypeRef cfOutData = (__bridge_retained CFTypeRef)outData; // Transfer ownership out of ARC.
*cfDataPtr = cfOutData;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
464 次 |
| 最近记录: |