I tried to write code that would be called when an object was freed by the swizzling method -[NSObject dealloc] . I understand that this is a bad idea and will not pursue it (therefore, please refrain from specifying this), but along the way I found that classes such as NSDictionary and NSString that duty-free connect with Core Foundation analogies such as CFDictionary and CFString do not call -dealloc after the final version.
This code demonstrates this phenomenon:
- (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); }
In the above tests, only a TestObject check will result in the release log being logged. Rewinding NSDictionary and NSString is not affected.
I suspect this is because the free bridge classes implement -release to execute CFRelease and not to call [super release] , so the memory is freed from Core Foundation and the -dealloc call is not made at all.
Can anyone confirm that this is documented? If so, is there a way to inject custom code into the release of these countless bridge classes?
source share