class_addMethodでクラスに追加されたメソッドを削除することはできますか?Objective-C 2.0で実行時にインスタンスメソッドを削除するにはどうすればよいですか?
これをやりたければ、実行時にobjc_allocateClassPairを使用してクラスを作成し続け、異なるメソッドセットを追加して実装されたメソッドを変更する必要がありますか?
私はハッカーを含む回答を受け入れるでしょう:-)
class_addMethodでクラスに追加されたメソッドを削除することはできますか?Objective-C 2.0で実行時にインスタンスメソッドを削除するにはどうすればよいですか?
これをやりたければ、実行時にobjc_allocateClassPairを使用してクラスを作成し続け、異なるメソッドセットを追加して実装されたメソッドを変更する必要がありますか?
私はハッカーを含む回答を受け入れるでしょう:-)
要するに、あなたはできません。経由でのObjective-C 1.0 ABI/APIで
あなたは可能性:
OBJC_EXPORT void class_removeMethods(Class, struct objc_method_list *) OBJC2_UNAVAILABLE;
しかし、メソッドを削除すると、かなり正しい答えになることはありませんので、その機能は、Objective-Cの2.0で削除されました。確かに、この機能をサポートすることによって発生するオーバーヘッドを正当化するのに十分ではない。
また、ObjC2.0 ABIから削除されたのは、クラス/メソッド構造に直接アクセスする能力でした。現在は不透明であるため、バイナリ互換性を損なうことなく将来変更することができます。
しかし、できることは、それが応答するメソッドのセットを変更するカスタムプロキシを使用することです。 NSProxyクラスのドキュメントを参照してください。 http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSProxy_Class/Reference/Reference.html
もちろん、この質問は「あなたは何をしようとしていますか?そのようなフライメタプログラミングは、非典型的です。クラスがインスタンス化されると、以前のインスタンス化が依然として上記のメソッドに依存する可能性があるという仮定の下で、それが応答するメソッドのセットを変更することは通常望ましいとは考えられません。
メソッドを正確に「削除」することはできませんが、すべてをメッセージ転送パス(最終的には-forwardInvocation:
を呼び出すコード)にリダイレクトするだけで、削除と同じ効果を得ることができます。それを達成するには、2つの方法があります。
_objc_msgForward()
、/usr/include/objc/message.h
で宣言されたが、オンラインドキュメントに含まれていない、あなたが削除しようとしているあなたの方法のためのIMP
として使用することができます。文書化されていないため、非公開またはサポートされていないと見なされる可能性があります。IMP
という結果を使用できます。ランタイムの代わりに実際のメソッドの実装に内部関数であってもよい戻さ関数ポインタ:ドキュメントに基づいて、これは、最初のオプションと同じ効果を有していなければなりません。たとえば、クラスのインスタンスがセレクタに応答しない場合、返される関数ポインタはランタイムのメッセージ転送機構の一部になります。いずれの場合も
、それはのように簡単になる:任意のスーパークラスは、有効なを持っている可能性がある場合は、より注意する必要がありますので、これは基本的に、任意のスーパークラスの実装を遮断することを
method_setImplementation(methodToRemove, forwardingIMP);
は注意あなたが保持したい実装。そのような場合は、スーパークラスまたはそれに類するものからIMP
を得ることができます。
「なぜ」という答えは、KVCが使用されたときの状況を示すコードを書くことに興味があることです。実行時にメソッドを追加したり削除したりすることで、メソッドのさまざまな組み合わせが存在するという効果をユーザーが探検できるようになりました。 私は、これを行うことができるのは、内部についてのことだけであると結論づけました。 Objective-C 2.0は、ハッカーを除いてすべての手段で停止しています。 –
少し遅いかもしれませんが、おそらくあなたのサンプルに、あなたが望むメソッドに応答する実行時に動的にサブクラスを作成することができます。メソッドを削除する代わりに、そのメソッドを持たない基本クラスの新しいサブクラスを作成するだけで済みます。 –
メソッドの削除が必要な別のケース:単体テストでは、既存のクラスのメソッドをスタブアウトする必要があることがあります。 OCMockフレームワークではこれを行うことができますが、OCMock自体ではメソッドを削除できないため、個々のテストの後にクラスを復元するのは困難です。既存のメソッドのIMPをスタブに置き換えることはできますが、そのメソッドが親クラスにあった場合は、そのサブクラスにスタブを追加して削除する必要があります。だから、あなたは何をしようとしているのですか?質問:私は完全に "懐疑的なソフトウェア"を得るが、私の意見では、Appleのランタイムはそれであってはならない。 –