I have a category on NSObject which supposed to so some stuff. When I call it on an object, I would like to override its dealloc method to do some cleanups.
I wanted to
Method selection is based on the class of an object instance, so method swizzling affects all instances of the same class - as you discovered.
But you can change the class of an instance, but you must be careful! Here is the outline, assume you have a class:
@instance MyPlainObject : NSObject
- (void) doSomething;
@end
Now if for just some of the instances of MyPlainObject
you'd like to alter the behaviour of doSomething
you first define a subclass:
@instance MyFancyObject: MyPlainObject
- (void) doSomething;
@end
Now you can clearly make instances of MyFancyObject
, but what we need to do is take a pre-existing instance of MyPlainObject
and make it into a MyFancyObject
so we get the new behaviour. For that we can swizzle the class, add the following to MyFancyObject
:
static Class myPlainObjectClass;
static Class myFancyObjectClass;
+ (void)initialize
{
myPlainObjectClass = objc_getClass("MyPlainObject");
myFancyObjectClass = objc_getClass("MyFancyObject");
}
+ (void)changeKind:(MyPlainObject *)control fancy:(BOOL)fancy
{
object_setClass(control, fancy ? myFancyObjectClass : myPlainObjectClass);
}
Now for any original instance of MyPlainClass
you can switch to behave as a MyFancyClass
, and vice-versa:
MyPlainClass *mpc = [MyPlainClass new];
...
// masquerade as MyFancyClass
[MyFancyClass changeKind:mpc fancy:YES]
... // mpc behaves as a MyFancyClass
// revert to true nature
[MyFancyClass changeKind:mpc: fancy:NO];
(Some) of the caveats:
You can only do this if the subclass overrides or adds methods, and adds static
(class) variables.
You also need a sub-class for ever class you wish to change the behaviour of, you can't have a single class which can change the behaviour of many different classes.