2012-02-11 1 views
4

渡されたクラスのメソッドを読んで、それらをすべて元のセレクタに転送する前に実行時に1つのセレクタにマップすることが理想的です。複数のメソッドswizzlesのメソッドIMPをコピーする

これは今でも動作しますが、一度に1つの方法でしか実行できません。問題は、一度私は最初のメソッドをswizzle、その方法をキャッチし、転送する私のIMPは、今は他のメソッドIMPと交換されているようだ。他のものを置き換えるために新しく交換されたIMPを使用するため、これ以上の試行はこれではねます。

1)したがって、私はMethodA、MethodB、およびCustomCatchAllMethodを持っています。

2)MethodAをCustomCatchAllMEthodと交換します。私はCustomCatchAllMethodを使ってMethodBにスワップしようとしていますが、CustomCatchAllMethod now = MethodA以降、MethodBはMethodAとMethodA-> MethodBになります。

それで、私が傍受したい新しいセレクターごとに、私のIMPの新しいインスタンスを取得/コピーするにはどうしたらいいですか?

ここでは上記の流れの大まかなモックアップだ:あなたが他のものと一つの方法をインターセプトしたいときの一般的な方法は、スウィズリングパターンのみ動作することを

void swizzle(Class classImCopying, SEL orig){ 
SEL new = @selector(catchAll:); 
Method origMethod = class_getInstanceMethod(classImCopying, orig); 
Method newMethod = class_getInstanceMethod(catchAllClass,new); 
method_exchangeImplementations(origMethod, newMethod); 
} 

//In some method elsewhere 

//I want this to make both methodA and methodB point to catchAll: 
swizzle(someClass, @selector(methodA:)); 
swizzle(someClass, @selector(methodB:)); 

答えて

3

が。あなたの場合は、基本的に実装をcatchAll:のどこかに挿入するのではなく、動かしています。

IMP imp = method_getImplementation(newMethod); 
method_setImplementation(origMethod, imp); 

しかしこれは一つの問題が残ります:元の実装に転送する方法?適切にこれを使用する必要があるだろうし


元のパターンはexchangeImplementationsを使用したものです。

あなたは可能性があなたの場合:

  • あなたはcatchAll:
  • からそれらへの呼び出しを構築することができますので、いくつかの共通の接頭辞を持つオリジナルのメソッドの名前を変更し、元の IMP周りSまたは
  • のテーブルを保ちます

同じ方法ですべてを転送する場合は、同じアリティのメソッドしか処理できないことに注意してください。

+0

ありがとうございます!私はそれで何がうまくいくか見るつもりです。私はすでに呼び出しを転送し、IMPSを格納するためのかなり洗練されたシステムを持っていますので、それほど大きな問題ではないはずです。 –

+0

それは本当にトリックをやったので、私はそれを逃したと信じることはできません。再度、感謝します! –

0

元のIMPをブロックで取得し、ブロックのIMPを取得し、メソッドの実装として設定することができます。

Method method = class_getInstanceMethod(class, setterSelector); 
SEL selector = method_getName(method); 
IMP originalImp = method_getImplementation(method); 

id(^block)(id self, id arg) = ^id(id self, id arg) { 
    return ((id(*)(id, SEL, id))originalImp)(self, selector, arg); 
}; 

IMP newImp = imp_implementationWithBlock(block); 
method_setImplementation(method, newImp); 
関連する問題