I have a custom object, it inherits from NSObject. This object does \"some things\", one of it is creating an UIView with some UIKit objects (UILabel, UIButtons ecc ecc...)
Nice implementation, I slightly modified the code and created the class as a subclass of NSProxy
. Using it in a project I found a memory leak:
For example: using the proxy to set global settings/appearance, each instance of that class will never reach refCount 0, so dealloc
will never be called.
Leak code:
-(void)forwardInvocation:(NSInvocation *)anInvocation;
{
[...]
// !! This will retain also the target
[anInvocation retainArguments];
[...]
}
Fix:
-(void)forwardInvocation:(NSInvocation *)anInvocation
{
[anInvocation setTarget:nil];
[anInvocation retainArguments];
// add the invocation to the array
[self.invocations addObject:anInvocation];
}
-(void)startForwarding:(id)sender
{
for (NSInvocation *invocation in self.invocations) {
// Create a new copy of the stored invocation,
// otherwise setting the new target, this will never be released
// because the invocation in the array is still alive after the call
NSInvocation *targetInvocation = [invocation copy];
[targetInvocation setTarget:sender];
[targetInvocation invoke];
targetInvocation = nil;
}
}
Copy category for NSInvocation
-(id)copy
{
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[self methodSignature]];
NSUInteger numberOfArguments = [[self methodSignature] numberOfArguments];
[invocation setTarget:self.target];
[invocation setSelector:self.selector];
if (numberOfArguments > 2) {
for (int i = 0; i < (numberOfArguments - 2); i++) {
char buffer[sizeof(intmax_t)];
[self getArgument:(void *)&buffer atIndex:i + 2];
[invocation setArgument:(void *)&buffer atIndex:i + 2];
}
}
return invocation;
}