为什么与Core Foundation对应的免费桥接的类在最终发布时不会调用-dealloc?

时间:2012-01-11 22:54:49

标签: objective-c ios

我试图编写一些代码,当通过调用-[NSObject dealloc]方法释放任何对象时将调用这些代码。我理解这是一个坏主意,不会追求它(所以请不要指出这一点),但是在此过程中我发现像NSDictionary和NSString这样的类是免费的,与CFDictionary等核心基础对应物桥接。和CFString在最终版本发布时不会调用-dealloc

此代码演示了这种现象:

- (void)loggedDealloc {
    NSLog(@"Deallocation of %@", self.class);
    [self loggedDealloc];
}

- (void)testDeallocSwizzleOnTestObject {
    Method deallocMethod = class_getInstanceMethod([TestObject class], NSSelectorFromString(@"dealloc"));
    Method loggedDeallocMethod = class_getInstanceMethod([self class], @selector(loggedDealloc));
    method_exchangeImplementations(deallocMethod, loggedDeallocMethod);

    TestObject * testObject = [[TestObject alloc] init];
    testObject = nil; // calls release under ARC

    method_exchangeImplementations(deallocMethod, loggedDeallocMethod);
}

- (void)testDeallocSwizzleOnNSDictionary {
    Method deallocMethod = class_getInstanceMethod([NSDictionary class], NSSelectorFromString(@"dealloc"));
    Method loggedDeallocMethod = class_getInstanceMethod([self class], @selector(loggedDealloc));
    method_exchangeImplementations(deallocMethod, loggedDeallocMethod);

    NSDictionary * dictionary = [[NSDictionary alloc] init];
    dictionary = nil; // calls release under ARC

    method_exchangeImplementations(deallocMethod, loggedDeallocMethod);
}

- (void)testDeallocSwizzleOnNSString {
    Method deallocMethod = class_getInstanceMethod([NSString class], NSSelectorFromString(@"dealloc"));
    Method loggedDeallocMethod = class_getInstanceMethod([self class], @selector(loggedDealloc));
    method_exchangeImplementations(deallocMethod, loggedDeallocMethod);

    NSDictionary * dictionary = [[NSDictionary alloc] init];
    dictionary = nil; // calls release under ARC

    method_exchangeImplementations(deallocMethod, loggedDeallocMethod);
}

在上面的测试中,只有Swizzling的测试对象才会导致重新分配的记录。 NSDictionary和NSString的混合没有效果。

我怀疑这是因为免费桥接类实现-release来执行CFRelease而不是调用[super release],因此内核被Core Foundation解除分配而没有调用-dealloc发生了。

任何人都可以确认是这种情况,是否记录在任何地方?如果是这样,有没有办法将自定义代码注入这些免费桥接类的解除分配?

1 个答案:

答案 0 :(得分:3)

(嘿。去过那里。做完了。:)

仅对各种类的子类保证对dealloc的调用。有许多类 - 主要是各种CF / NS桥接类 - 从未调用dealloc,因为从来没有必要这样做[内部实现细节]。

要做你想做的事情,将子类化为所需的类,将原始类的实例封装为后备存储,然后覆盖原始方法(每个类集群类都有一个非常小的集合)原始方法 - 我认为NSString具有所有2种方法)然后覆盖该新类的内存管理方法。因为它是一个子类,你在现有类中看到的“短路”将不再发挥作用。