I was having memory leaks in my project from AnimatedGIFImageSerialization, like in issue https://github.com/mattt/AnimatedGIFImageSerialization/issues/11
I tried similar swizzling with a custom test class, and noticed that if we swizzle a static creation method with __attribute__((objc_method_family(init)))
(like animated_gif_imageWithData:
and animated_gif_imageWithData:scale:
), the returned object will not be deallocated . If swizzle with __attribute__((objc_method_family(new)))
(like animated_gif_imageWithContentsOfFile:
), it will be deallocated, but at some weird different time compared to when running without swizzling. I had this test:
@implementation TestClass
// whatever
- (void)dealloc {
NSLog(@"TestClass instance Died! %@", _crab);
}
@end
// in some swizzling category
+ (TestClass*)sqwizzled_testClassWithCrab:(NSObject*)crab
__attribute__((objc_method_family(new)))
// if set "init" here, object will not be deallocated - leak!
// if set "new" here, object will be deallocated but at a different time than when using a non-swizzled method
// so best not to set attribute and things will work out themselves
{
NSLog(@"sqwizzled_testClassWithCrab %@", crab);
// simply call through to original
return [self sqwizzled_testClassWithCrab:crab];
}
........
// in some ViewController
- (void)viewDidLoad {
[super viewDidLoad];
for (int i = 5; i < 10; i ++) {
TestClass * testClass = [TestClass testClassInstanceWithCrab:@(i)];
// something something
}
NSLog(@"2nd loop end");
}
When testClassInstanceWithCrab was not swizzled, the output was like this:
2016-10-04 14:17:53.556 SwizzlingTest[10185:261562] TestClass instance Died! 5
2016-10-04 14:17:53.556 SwizzlingTest[10185:261562] TestClass instance Died! 6
2016-10-04 14:17:53.556 SwizzlingTest[10185:261562] TestClass instance Died! 7
2016-10-04 14:17:53.556 SwizzlingTest[10185:261562] TestClass instance Died! 8
2016-10-04 14:17:53.557 SwizzlingTest[10185:261562] TestClass instance Died! 9
2016-10-04 14:17:53.557 SwizzlingTest[10185:261562] 2nd loop end
With "init" family messages from dealloc were never printed.
But when swizzled with __attribute__((objc_method_family(new)))
, the output is a bit different
2016-10-04 14:19:39.474 SwizzlingTest[10213:264787] sqwizzled_testClassWithCrab 5
2016-10-04 14:19:39.474 SwizzlingTest[10213:264787] sqwizzled_testClassWithCrab 6
2016-10-04 14:19:39.475 SwizzlingTest[10213:264787] sqwizzled_testClassWithCrab 7
2016-10-04 14:19:39.475 SwizzlingTest[10213:264787] sqwizzled_testClassWithCrab 8
2016-10-04 14:19:39.475 SwizzlingTest[10213:264787] sqwizzled_testClassWithCrab 9
2016-10-04 14:19:39.475 SwizzlingTest[10213:264787] 2nd loop end
2016-10-04 14:19:39.477 SwizzlingTest[10213:264787] TestClass instance Died! 9
2016-10-04 14:19:39.477 SwizzlingTest[10213:264787] TestClass instance Died! 8
2016-10-04 14:19:39.477 SwizzlingTest[10213:264787] TestClass instance Died! 7
2016-10-04 14:19:39.477 SwizzlingTest[10213:264787] TestClass instance Died! 6
2016-10-04 14:19:39.478 SwizzlingTest[10213:264787] TestClass instance Died! 5
As seen objects are deallocated not immediately like normally, but when method scope ended for some reason. So I removed __attribute__((objc_method_family(new)))
from animated_gif_imageWithContentsOfFile: