質問

Objective-Cの IMP タイプは、私が理解している限り、関数ポインターを表します。ブロックポインターから IMP を作成する方法はありますか?あなたのアイデアをありがとう。

役に立ちましたか?

解決

これが書かれて以来、iOSとMac OS Xには、ブロックを直接IMPに変換できるAPIがあります。 ウェブログの投稿を書きましたAPI(imp_implementationWithBlock())。


ブロックは、実質的に、メタデータの一部、ブロック内に含まれるコードへの参照、およびブロック内でキャプチャされたconstコピーされたデータのコピーを含む構造です。

したがって、いいえ、 IMP とブロック参照を直接マッピングする方法はありません。

ブロックの呼び出しがコンパイルされると、コンパイラーはスタックフレームを設定するトランポリンを出力し、ブロック内の実行可能コードにジャンプします。

ただし、できることは、そのトランポリンのように動作するIMPを作成することです。以下の場合、引数のセットごとに1つの特定のIMPが必要になります&呼び出される型を返します。これをジェネリックにする必要がある場合は、アセンブリを使用する必要があります。

このため、クラスのインスタンスごとに一意のブロックインスタンスを設定しています。すべてのインスタンスで機能する汎用ブロックが必要な場合は、 SEL のハッシュを作成します->クラスごとにブロックします。

(1)関連する参照メカニズムを使用して、IMPとして機能するブロックを関連付けます。次のようなもの:

void (^implementingBlock)(id s, SEL _c, int v) = ^(id s, SEL _c, int v) {
     // do something here
}

objc_setAssociatedObject(obj, SELToImp, [implementingBlock copy]));

(2)次のようなトランポリンIMPを実装します。

void void_id_sel_intTramp(id self, SEL _cmd, int value) {
    int (^block)(id s, SEL _c, int v) = objc_getAssociatedObject(self, _cmd);
    block(self, _cmd, value);
}

(3)上記のトランポリンをObjective-CランタイムのAPIを介してセレクターに挿入します( method_setImplementation などを参照)

警告:

  • これはStackOverflowに入力されました。実際のコードは似ていますが、わずかに異なる可能性があります。

  • [implementingBlock copy]は重要です。ブロックはスタックでのライフを開始します(通常)

他のヒント

マイク・アッシュは、ランドン・フラーの助けを借りて、iOSを含む一般的なケースでこれを解決したと思います。彼は github にクラスを持ち、ブロックを関数ポインターに変換します。

お知らせといくつかのココアアンバウンドに関する興味深いフォローアップディスカッション。

更新:そして、上記のように imp_implementationWithBlock()があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top