【发布时间】:2009-08-22 04:55:04
【问题描述】:
是否可以使用 class_addMethod 删除添加到类的方法?
或者如果我想这样做,我必须在运行时继续使用 objc_allocateClassPair 创建类并向它们添加不同的方法集以改变实现的方法吗?
我会接受包含骇客的答案:-)
【问题讨论】:
标签: objective-c runtime
是否可以使用 class_addMethod 删除添加到类的方法?
或者如果我想这样做,我必须在运行时继续使用 objc_allocateClassPair 创建类并向它们添加不同的方法集以改变实现的方法吗?
我会接受包含骇客的答案:-)
【问题讨论】:
标签: objective-c runtime
您不能完全“删除”一个方法,但您可以获得与删除相同的效果,方法是使该方法将所有内容重定向到消息转发路径(最终将调用 -forwardInvocation: 的代码)。有两种方法可以实现:
_objc_msgForward(),在/usr/include/objc/message.h 中声明但不包含在在线文档中,可以用作您尝试删除的方法的IMP。因为它没有记录,它可能被认为是私有的或不受支持的。IMP。根据文档,这应该与第一个选项具有相同的效果:返回的函数指针可能是运行时内部的函数,而不是实际的方法实现。例如,如果类的实例不响应选择器,则返回的函数指针将成为运行时消息转发机制的一部分。
无论哪种情况,它都变得如此简单:
method_setImplementation(methodToRemove, forwardingIMP);
请注意,这基本上会阻止任何超类实现,因此如果任何超类可能具有您想要保留的有效实现,您必须更加小心。在这种情况下,您可以从超类或类似的东西中获取IMP。
【讨论】:
简而言之,你不能。
您可以在 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
当然,这个问题引出了“你想做什么?”的问题。这种动态元编程是非典型的。一旦一个类被实例化,在假设之前的实例化可能仍然依赖于所述方法的假设下,通常认为不希望更改它响应的方法集。
【讨论】: