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メソッドは、selfと_cmdの少なくとも2つの引数を取る単純なC関数です。たとえば、次の関数があるとします。

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

ブロック型のパラメーターとして関数ポインターを渡していますが、ブロックは関数ポインターではありません。簡単な例として、次のコードは の 2 回目の呼び出しでクラッシュします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 });

非常に動的なことをしているように見えるので、後で使用するためにブロックをどこかに動的に保存する方法を見つける必要があるかもしれません。これはオブジェクトであり、後で使用するためにヒープ割り当てブロックへのポインターを取得する関数を-copy使用して目的の C でメソッドを使用するか、純粋な C API でコピーしたり、コレクションに格納したりできます。Block_copy()

于 2013-02-11T09:56:55.513 に答える