Discovering at runtime which of a class' instance variables are declared __weak

前端 未结 1 1793
梦谈多话
梦谈多话 2020-12-15 00:22

I\'m writing a tool which would benefit from knowing which of a class\' instance variables are declared __weak.

This information must exist somewher

相关标签:
1条回答
  • 2020-12-15 00:52

    Alright, here is a sample implementation, using a custom object implementation, that does a rudimentary check to see if an iVar is weak or not:

    BOOL iVarIsWeak(Class cls, Ivar ivar)
    {
        id classInstance = [cls new];
    
        // our custom base class properly tracks reference counting, no weird voodoo
        id refCounter = [CustomBaseClass new];
    
        object_setIvar(classInstance, ivar, refCounter);
    
        if ([refCounter refCount] == 2)
        {
            return NO;
        }
    
        return YES;
    }
    

    The above code is meant to be used with ARC enabled, while the following custom object code is not:

    @interface CustomBaseClass : NSObject
    
    +(id) new;
    +(id) alloc;
    -(id) init;
    
    -(id) retain;
    -(void) release;
    -(id) autorelease;
    -(void) dealloc;
    
    -(id) description;
    
    -(unsigned) refCount;
    
    @end
    
    
    // easy way to get sizeof
    struct CustomBaseClassAsStruct {
        voidPtr isa;
        unsigned volatile refcount;
    };
    
    @implementation CustomBaseClass
    {
        unsigned volatile  refcount;
    }
    
    +(id) new
    {
        return [[self alloc] init];
    }
    
    +(id) alloc
    {
        struct CustomBaseClassAsStruct *results =  malloc(sizeof(struct CustomBaseClassAsStruct));
        results->isa = self;
        results->refcount = 0;
        return (id) results;
    }
    
    -(id) init
    {
        [self retain];
    
        return self;
    }
    
    -(id) retain
    {
        ++refcount;
    
        return self;
    }
    
    -(void) release
    {
        if (--refcount == 0)
            [self dealloc];
    }
    
    -(id) autorelease
    {
        // sample implementation of autorelease
        dispatch_async(dispatch_get_current_queue(), ^{
            [self release];
        });
    
        return self;
    }
    
    -(unsigned) refCount
    {
        return refcount;
    }
    
    -(void) dealloc
    {
        free(self);
    
        // no call to [super dealloc], we are using custom memory-managment
    }
    
    @end
    

    This ONLY works for weak iVars. With a unsafe_unretained variable, it will give a false positive, my best guess for this is because __weak information is saved at runtime whilst unsafe_unretained information is not.

    I hope this helps!

    0 讨论(0)
提交回复
热议问题