另一种方法是使用动态子类:
- (void)addCustomMethodToObject:(id)object {
Class objectClass = object_getClass(object);
SEL selectorToOverride = ...; // this is the method name you want to override
NSString *newClassName = [NSString stringWithFormat:@"Custom_%@", NSStringFromClass(objectClass)];
Class c = NSClassFromString(newClassName);
if (c == nil) {
// this class doesn't exist; create it
// allocate a new class
c = objc_allocateClassPair(objectClass, [newClassName UTF8String], 0);
// get the info on the method we're going to override
Method m = class_getInstanceMethod(objectClass, selectorToOverride);
// add the method to the new class
class_addMethod(c, selectorToOverride, (IMP)myCustomFunction, method_getTypeEncoding(m));
// register the new class with the runtime
objc_registerClassPair(c);
}
// change the class of the object
object_setClass(object, c);
}
id myCustomFunction(id self, SEL _cmd, [other params...]) {
// this is the body of the instance-specific method
// you may call super to invoke the original implementation
}
这样做之后,onlyobject
将收到被覆盖的方法,因为它将是唯一一个特殊类的实例。此外,此代码仅覆盖实例方法,但修改它以覆盖类方法并不难。
与往常一样,通常的警告:
- 警告实施者:此代码是在浏览器中输入的
- 警告观察者:此代码不能很好地与键值观察配合使用
- 警告线程:这段代码看起来不是很线程安全
- 警告 ARC'er:
objc_allocateClassPair()
不能用 ARC 编译。
- 警告开发人员:乱搞一个对象的类是一件危险的事情。这种巫毒有完全合法的用途,但它们非常罕见。如果你认为你需要这样做,你可能是错的,应该在这里发布一个新问题:“这是我认为我需要做的;是吗?”