Is it possible to remove methods added to a class with class_addMethod?
Or if I want to do this, must I keep creating classes at runtime with objc_allocateClassPair and adding different sets of methods to them to vary the methods implemented?
I'll accept answers that include hackery :-)
You can't exactly "remove" a method, but you can get the same effect as a removal, by making the method just redirect everything to the message forwarding path (the code that will eventually call -forwardInvocation:
). There are two ways to accomplish that:
_objc_msgForward()
, declared in /usr/include/objc/message.h
but not included in the online documentation, can be used as the IMP
for your method you are trying to remove. Because it's undocumented, it may be considered private or unsupported.IMP
for the method you are trying to remove. Based on the documentation, this should have the same effect as the first option:The function pointer returned may be a function internal to the runtime instead of an actual method implementation. For example, if instances of the class do not respond to the selector, the function pointer returned will be part of the runtime's message forwarding machinery.
In either case, it becomes as simple as:
method_setImplementation(methodToRemove, forwardingIMP);
Note that this will basically block out any superclass implementations, so you'll have to be more careful if any superclass might have a valid implementation that you want to keep. In such a case, you could get the IMP
from the superclass or something similar.
In short, you can't.
You could in the Objective-C 1.0 ABI/API via:
OBJC_EXPORT void class_removeMethods(Class, struct objc_method_list *) OBJC2_UNAVAILABLE;
But that function was removed in Objective-C 2.0 because removing methods is pretty much never the right answer. Certainly not often enough to justify the overhead incurred by supporting said feature.
Also removed from the ObjC2.0 ABI was the ability to directly access the class/method structures. They are now opaque so that they can be changed in the future without breaking binary compatibility.
What you could do, though, is use a custom proxy that varies the set of methods that it responds to. See documentation for the NSProxy class; http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSProxy_Class/Reference/Reference.html
Of course, this question begs the question "What are you trying to do?". Such on the fly meta-programming is atypical. Once a class is instantiated, it isn't normally considered desirable to change the set of methods it responds to under the assumption that previous instantiations may still depend on said methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With