Gil*_*vik 17 methods objective-c categories swizzling ios
我在NSObject上有一个类别应该是这样的东西.当我在一个对象上调用它时,我想覆盖它的dealloc方法来进行一些清理.
我想用方法调配来做,但无法弄清楚如何.我发现的唯一例子是关于如何替换整个类的方法实现(在我的例子中,它将覆盖所有NSObjects的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
Sve*_*ven 19
你不能真的这样做,因为对象没有自己的方法表.只有类具有方法表,如果更改它们,它将影响该类的每个对象.但是有一种简单的方法:在运行时将对象的类更改为动态创建的子类.这种技术,也称为isa-swizzling,被Apple用来实现自动KVO.
这是一种功能强大的方法,它有其用途.但对于您的情况,使用关联对象的方法更简单.基本上你用来objc_setAssociatedObject将另一个对象与你的第一个对象关联起来dealloc.你可以在这篇关于Cocoa is my Girlfriend的博客文章中找到更多细节.
CRD*_*CRD 10
方法选择基于对象实例的类,因此方法调配会影响同一类的所有实例 - 正如您所发现的那样.
但是您可以更改实例的类,但必须小心!这是大纲,假设你有一个类:
@instance MyPlainObject : NSObject
- (void) doSomething;
@end
现在,如果只是MyPlainObject为了改变doSomething你的行为的某些实例,首先要定义一个子类:
@instance MyFancyObject: MyPlainObject
- (void) doSomething;
@end
现在你可以清楚地创建实例MyFancyObject,但我们需要做的是采用预先存在的实例MyPlainObject并将其变为一个实体,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您可以切换为表现为a 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(类)变量.
你还需要一个你希望改变行为的类的子类,你不能拥有一个可以改变许多不同类的行为的类.
| 归档时间: | 
 | 
| 查看次数: | 5224 次 | 
| 最近记录: |