目标C:创建后的swizzle对象方法

时间:2012-03-30 19:27:35

标签: iphone objective-c ios

我想在创建对象后调用对象方法。

示例:

@interface MyObj: NSObject
-(NSString*) foo;
-(NSString*) bar;
@end

@implementation MyObj
-(NSString*) foo {return @"foo";}
-(NSString*) bar {return @"bar";}
@end

void Swizzle(object, SEL source, SEL, dest);

...

MyObj* obj = [[[MyObj alloc] init] autorelease];

NSLog(@"%@", [obj foo]);
Swizzle(obj, @selector(foo), @selector(bar));
NSLog(@"%@", [obj foo]);

输出:

foo
bar

在创建对象之前,我已经查看了很多examples的混合。但是,正如您所看到的,我想在创建对象后进行调整。

这是因为我想跟踪要发布的对象(比如NSThread)。我不想调动NSObject dealloc,因为这看起来有点过分。我宁愿只调动我想跟踪的物体。

3 个答案:

答案 0 :(得分:3)

这显然是一种不明智的尝试,以避免使用仪器。如果是这样,正确答案是“只使用仪器。”

但要真正回答这个问题:你不能用单个对象做到这一点。方法 - 甚至实例方法 - 是按类定义的,而不是按对象定义的。在每个对象的基础上覆盖方法的唯一方法是动态创建对象类的子类,该子类覆盖您感兴趣的方法,并且isa-swizzle对象,因此它使用子类的查找表。 (这基本上就是KVO在引擎盖下发出魔法通知的方式。)同样,这是一个黑客攻击,通常比它的价值更麻烦,所以在你这样做之前,我真的会三思而后行(或三次) )这是否真的有必要。对于我能想到的几乎任何用例,有一种更简洁的方法来实现不涉及运行时巫术的相同目标。

答案 1 :(得分:1)

你不能混淆一个对象,只能一个特定的类。此外,缓存了选择器的实现,并且当您调用时可能不会自动清除该缓存,这意味着不使用新方法。

我建议在您要跟踪的班级中覆盖(或调整)dealloc,并使用属性来确定是否应该执行跟踪代码。

@property (nonatomic) BOOL shouldTrackDealloc;

@synthesize shouldTrackDealloc;
- (void)dealloc {
    if(self.shouldTrackDealloc) {
        NSLog(@"dealloc of %@",self);
    }
    ...
}

如果您正在跟踪框架类,则无法使用@synthesize,因为实例变量不在正确的类中,但您可以改为使用associated references

答案 2 :(得分:0)

我最终得到的解决方案是使用objc_setAssociatedObject(线程,密钥,对象,OBJC_ASSOCIATION_RETAIN_NONATOMIC);

这样我可以检测线程何时被释放并进行我需要的清理。