1

所以我试图调用一个具有回调代码块作为参数的Objective-C方法。

Objective-C 方法(为了发布的目的而削减实现)

- (void)requestWithCompletionHandler:(void(^)(BOOL, NSArray*))completionHandler {

    // Implementation ...

    completionHandler(YES, NSArray...);

}

C 代码(rsc保存已分配和启动的类)

void callback(id self, SEL _cmd, BOOL success, CFArrayRef array)
{
    printf("BOOM\n");
}

objc_msgSend(rsc, sel_getUid("requestWithCompletionHandler:"), (IMP)callback);

来自 Apple 文档

id objc_msgSend(id theReceiver, SEL theSelector, ...)

还...

Objective-C 方法只是一个 C 函数,它至少有两个参数——self 和 _cmd。例如,给定以下函数:

void myMethodIMP(id self, SEL _cmd)
{
    // implementation ....
}

您可以将其作为方法(称为 resolveThisMethodDynamically)动态添加到类中,如下所示:

class_addMethod([self class], @selector(resolveThisMethodDynamically), (IMP) myMethodIMP, "v@:");

但是,运行时我得到一个EXC_BAD_ACCESS

4

2 回答 2

1

有趣的是,这比我最初想象的要容易。您只需传递一个实际的代码块作为参数。

objc_msgSend((id)rsc, sel_getUid("requestWithCompletionHandler:"), ^(BOOL success, CFArrayRef array) {
        if (success) {
            printf("BOOM\n");
        }});
于 2013-02-11T09:43:54.270 回答
1

您将函数指针作为块类型的参数传递,但块不是函数指针。作为一个简单的示例,以下代码将在第二次调用时崩溃takesABlock()

#include <stdio.h>
#include <dispatch/dispatch.h>

void function1();
void takesABlock(dispatch_block_t block);

int main(int argc, const char * argv[])
{

    dispatch_block_t block = ^{ printf("In a block\n"); function1(); };
    takesABlock(block);
    takesABlock((dispatch_block_t)function1);
}

void function1() {
    printf("In function1\n");
}

void takesABlock(dispatch_block_t block) {
    block();
}

因此,您需要传递一个实际的块:

objc_msgSend(rsc, sel_getUid("requestWithCompletionHandler:"), ^(BOOL aBool, NSArray *anArray){ // block code here });

看起来您正在做一些高度动态的事情,因此您可能需要找到一种方法将块动态存储在某处以供以后使用。它是一个对象,可以通过复制、存储在集合中等方式在 Objective-C 中使用该-copy方法或在纯 C API 中通过使用该Block_copy()函数获取指向堆分配块的指针以供以后使用。

于 2013-02-11T09:56:55.513 回答