2012-07-23 8 views
8

Estoy escribiendo una herramienta que se beneficiaría de saber qué variables de instancia de una clase se declaran __weak.Descubriendo en tiempo de ejecución cuál de las variables de instancia de una clase se declara __weak

Esta información debe existir en algún lugar en tiempo de ejecución, pero ¿hay alguna forma de acceder a ella, documentada o no? (Es para una herramienta, así que no me importa tanto romper con las actualizaciones)

+0

Esta pregunta me ha llamado la atención, así que si no obtiene una respuesta, no se preocupe, estoy trabajando en ello –

+0

¿Importa si el iVar es 'unsafe_unretained' vs' weak'? Si no, eso hace que mi vida sea mucho más fácil. –

+0

fuerte vs no fuerte es la distinción en la que estoy interesado. –

Respuesta

4

Bien, aquí hay una implementación de ejemplo, usando una implementación de objeto personalizada, que hace una comprobación rudimentaria para ver si un iVar es débil o no:

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

el código anterior está destinado a ser utilizado con ARC activada, mientras que el siguiente código de objeto personalizado no es:

@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 

esto sólo funciona para Ivars débiles. Con una variable unsafe_unretained, dará un falso positivo, mi mejor estimación es que la información __weak se guarda en el tiempo de ejecución mientras que la información unsafe_unretained no lo está.

Espero que esto ayude!

+0

Interesante. Pensé que el tiempo de ejecución solo necesitaba información sobre almacenamiento para eliminar las referencias débiles al desasignar, pero no había considerado que object_setIvar también lo necesitaría (aunque tiene sentido dado que object_setInstanceVariable está prohibido en ARC). Probablemente debería tratar '__unsafe_unretained' de forma similar a' __weak'. Voy a presentar un error. –

Cuestiones relacionadas