解除分配任何Object之前的回调方法

时间:2011-05-11 06:19:02

标签: iphone objective-c cocoa-touch cocoa

在解除分配任何NSObject类对象之前,有没有办法调用方法。

是否可以为NSObject类编写自定义dealloc方法以便使用 我们可以在解除分配该对象之前调用任何方法吗?

由于垃圾收集器不适用于iPhone,我想创建一个在运行时处理内存泄漏的小框架。为泄漏创建一个日志文件(我知道有一个工具可以识别泄漏但仍然用于R& D并且不想实现垃圾收集器算法)。

我们正在尝试维护已分配对象的列表。

例如:

A *a=[[A alloc]init];

NSString * veribaleAddress=[NSString stringWithFormat:@"%p",&a];

NSString *allocatedMemoryAddress=[NSString stringWithFormat:@"%p",a];

// Global dictionary for maintaining a list of object  NSMutableDictionary *objects;


[objects setValue: allocatedMemoryAddress forKey: veribaleAddress];

但是当任何对象获得解除分配时,我想先看一下,该对象的地址是否存在于字典中。如果地址存在,则将其从字典中删除。

请指导我,无论是否可能。

由于

2 个答案:

答案 0 :(得分:9)

这是一个example gist,展示如何swizzle dealloc方法,如果这就是你所追求的。代码的主要部分:

void swizzle(Class c, SEL orig, SEL patch)
{
    Method origMethod = class_getInstanceMethod(c, orig);
    Method patchMethod = class_getInstanceMethod(c, patch);

    BOOL added = class_addMethod(c, orig,
        method_getImplementation(patchMethod),
        method_getTypeEncoding(patchMethod));

    if (added) {
        class_replaceMethod(c, patch,
            method_getImplementation(origMethod),
            method_getTypeEncoding(origMethod));
        return;
    }

    method_exchangeImplementations(origMethod, patchMethod);
}

id swizzledDealloc(id self, SEL _cmd)
{
    // …whatever…
    return self;
}

const SEL deallocSel  = @selector(dealloc);
// If using ARC, try:
//  const SEL deallocSel  = NSSelectorFromString(@"dealloc");

const SEL swizzledSel = @selector(swizzledDealloc);
class_addMethod(c, swizzledSel, (IMP) swizzledDealloc, "@@:");
swizzle(c, deallocSel, swizzledSel);

正如巴伐利亚所说,这是黑魔法,我不会在生产中使用它。

答案 1 :(得分:3)

您可以使用objc_setAssociatedObject来跟踪对象的生命周期。像这样:

部首:

// SGBObjectTracker.h

typedef void (^SGBObjectTrackerCallback)(id trackedObject); 

@interface SGBObjectTracker : NSObject

@property (nonatomic, assign) id trackedObject;
@property (nonatomic, copy) SGBObjectTrackerCallback callback;

+(void) trackObject:(id)object withCallback:(SGBObjectTrackerCallback)callback;

@end

实现:

// SGBObjectTracker.m

#import "SGBObjectTracker.h"
#import <objc/runtime.h>

@implementation 

@synthesize trackedObject, callback;

-(void) dealloc
{
    callback(trackedObject);
    [super dealloc];
}

+(void) trackObject:(id)object withCallback:(SGBObjectTrackerCallback)callback
{
    SGBObjectTracker *tracker = [[self alloc] init];
    tracker.callback = callback;
    tracker.trackedObject = object;
    objc_setAssociatedObject(object, _cmd, tracker, OBJC_ASSOCIATION_RETAIN);
    [tracker release];
}

@end

这利用了以下事实:关联对象在与其关联的对象被释放时被释放。它不适用于NSZombies启用,如果您使用ARC或其他与保留计数混淆的东西,它可能会破坏。我不会指望在回调期间能够使用有问题的对象,但它的地址应该仍然没问题,而这正是你所需要的。