将Objective-C对象作为void*指针传递给函数

Ben*_*ley 14 pointers casting objective-c callback

我有一个功能:

  myFunction (MyProc callback, void * ref)
Run Code Online (Sandbox Code Playgroud)

从Objective-C类中调用此函数.该函数传递一个指向回调(类中的函数)和引用的指针.引用是必要的,因为回调是静态调用的,因此没有上下文.ref可用于为回调提供上下文.

我希望能够传递Objective-C类作为参考.所以问题是:

如何将NSObject转换为void*以及如何将void*转换为NSObject.

提前致谢.

bbu*_*bum 33

做这样的事情:

void func(void *q)
{
    NSObject* o = CFBridgingRelease(q);
    NSLog(@"%@", o);
}

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSObject* o = [NSObject new];
        func((void*)CFBridgingRetain(o));
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

请注意,CFBridgingRetain()并且CFBridgingRelease()是围绕编译器属性的宏.随意使用.我喜欢API变体,因为它在我们的代码库中更常见,并且更明确/更少混淆.

CFBridgingRetain()有效地硬保留必须由a平衡的对象CFBridgingRelease().这也恰好返回CFTypeRef一个强制转换为兼容void*. CFBridgingRelease()有效地撤销了难以保留的内容,因此q只会在有效范围内保持o有效.

适用于基本的回调,但你可能不是那种void *context;类型的东西必须坚持一段时间.为了那个原因:

void callback(void *context)
{
    // grab an ARC aware reference without impacting hard-retain
    NSObject* o = (__bridge NSObject *)(context);
    NSLog(@"%@", o);
}

void freeContext(void *context)
{
    // release the hard-retain
    CFBridgingRelease(context);
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果省略cast/API调用,Xcode非常适合建议您应该做什么.它甚至解释了每种替代解决方案的含义(我依靠这一点,直到我能够直接将它们放在我的脑海中).


tia*_*tia 7

我假设您正在使用ARC.你可以在打电话时使用这样的东西myFunction

id ref = ...; // your Objective-C object
myFunction(callback, (__bridge_retained void *) ref);
Run Code Online (Sandbox Code Playgroud)

在回调中,您必须转回所有权:

void callback(void* refPtr) {
    id refObj = (__bridge_transfer id) refPtr;
}
Run Code Online (Sandbox Code Playgroud)

替换id为适当的对象类型.