一个单一的实例,而不是一个类

我有一个类NSObject应该这样做的东西。 当我在对象上调用它时,我想重写它的dealloc方法来做一些清理。

我想使用方法swizzling做,但无法弄清楚如何。 我发现的唯一例子是如何replace整个类的方法实现(在我的情况下,它会覆盖所有NSObject的dealloc – 我不想)。

我想重写NSObject的特定实例的dealloc方法。

@interface NSObject(MyCategory) -(void)test; @end @implementation NSObject(MyCategory) -(void)newDealloc { // do some cleanup here [self dealloc]; // call actual dealloc method } -(void)test { IMP orig=[self methodForSelector:@selector(dealloc)]; IMP repl=[self methodForSelector:@selector(newDealloc)]; if (...) // 'test' might be called several times, this replacement should happen only on the first call { method_exchangeImplementations(..., ...); } } @end 

你不能这样做,因为对象没有自己的方法表。 只有类有方法表,如果你改变它,它会影响该类的每个对象。 有一个简单的方法可以解决这个问题:在运行时将对象的类更改为dynamic创build的子类。 这种技术也被称为isa-swizzling,被苹果用来实现自动KVO。

这是一个强大的方法,它有它的用途。 但是对于你的情况,使用关联对象有一个更简单的方法。 基本上你使用objc_setAssociatedObject将另一个对象关联到你的第一个对象,它在dealloc中进行清理。 你可以在这个博客文章中find更多的细节cocoa是我的女朋友 。

方法select基于对象实例的 ,所以方法调整会影响同一个类的所有实例 – 正如您发现的那样。

但是你可以改变一个实例的类,但你一定要小心! 这里是轮廓,假设你有一个类:

 @instance MyPlainObject : NSObject - (void) doSomething; @end 

现在,如果仅仅是一些MyPlainObject的实例,你想改变doSomething的行为,你首先定义一个子类:

 @instance MyFancyObject: MyPlainObject - (void) doSomething; @end 

现在,您可以清楚地创buildMyFancyObject实例,但是我们需要做的是将已有MyPlainObject实例创build为MyFancyObject以便获得新的行为。 为此,我们可以调整类,添加以下到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); } 

现在,对于MyPlainClass任何原始实例,您都可以切换为MyFancyClass ,反之亦然:

 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]; 

(一些)的注意事项:

如果子类重写或添加方法,并且添加static (类)variables,则只能这样做。

你还需要一个你想改变行为的类的子类,你不能拥有一个可以改变许多不同类的行为的类。

我做了一个swizzling的API,也具有特定于实例的swizzling。 我想这正是你正在寻找的: https : //github.com/JonasGessner/JGMethodSwizzler

它的工作原理是在运行时为特定的实例创build一个dynamic的子类。