UIAppearance proxy for custom objects

前端 未结 4 543
小鲜肉
小鲜肉 2020-12-24 14:48

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...)

4条回答
  •  [愿得一人]
    2020-12-24 14:59

    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;
    }
    

提交回复
热议问题