2010-12-13 22 views
10

EDITAR: No voy a hacer esto, ahora me doy cuenta de lo peligroso que puede ser esto. Pero, la pregunta se mantiene con fines puramente académicos.Accediendo a la variable privada en la categoría resultados en el error del enlazador

Estoy tratando de implementar una categoría en NSCollectionView que me permita acceder a la variable privada _displayedItems. Necesito poder acceder a él en mi subclase. Por lo tanto, he creado la siguiente categoría:

@interface NSCollectionView (displayedItems) 

- (NSMutableArray *)displayedItems; 

@end 


@implementation NSCollectionView (displayedItems) 

- (NSMutableArray *)displayedItems 
{ 
    return _displayedItems; 
} 

@end 

... que parece que debería funcionar a la perfección. Sin embargo, cuando intento compilar esto, el enlazador me da el siguiente error:

Undefined symbols: 
    "_OBJC_IVAR_$_NSCollectionView._displayedItems", referenced from: 
     -[NSCollectionView(displayedItems) displayedItems] in NSCollectionView+displayedItems.o 
ld: symbol(s) not found 
collect2: ld returned 1 exit status 

Sé que es un hecho de que _displayedItems existe en NSCollectionView, he mirado en la interfase y también imprimió su contenido utilizando el BGF. ¿Alguien sabe de una manera de arreglar esto?

¡Gracias de antemano!
Billy

+0

He encontrado que esta es la mejor respuesta. Fácil, simple y seguro: http: // stackoverflow.com/questions/16678463/accessing-a-method-in-a-super-class-when-its-not-exposed –

Respuesta

12

_displayedItems es un ivar privado, por lo que no debe acceder, incluso desde una categoría.

Dicho esto, usted debe tratar de compilar el mismo código con

gcc -arch i386 

y

gcc -arch x86_64 

y ver la diferencia. En el modo de 32 bits, no ve el error. Esto muestra cuán frágil es la situación. Realmente no deberías.

Dicho esto, hay una manera de conseguir que Ivar abusando KVC:

@implementation NSCollectionView (displayedItems) 

- (NSMutableArray *)myDisplayedItems 
{ 
    return [self valueForKey:@"displayedItems"]; 
} 

@end 

Tenga en cuenta que no se debe nombrar a su método tan displayedItems. Eso haría un ciclo infinito, porque la maquinaria KVC encontraría su método antes que el ivar. Ver here.

O puede acceder a cualquier ivar oculto utilizando las funciones de tiempo de ejecución Objective-C. Eso también es divertido

Sin embargo, permítanme decirlo de nuevo. Hay una gran diferencia en saber que puedes hacer una cosa y hacerlo de verdad. Solo piensa en cualquier crimen horrible. y hacer eso por ti mismo.

¡NO HAGAS ESO!

+0

Muy bien, lo entiendo, mala idea. :) ¡Gracias de cualquier manera! – vilhalmer

+1

Me gustaría mover el "no hagas eso" a la cima. :) Si empiezas a perder el tiempo con el estado interno de las clases framework, seguro que te sorprenderán los fallos y las misteriosas fallas con el tiempo. – bbum

+0

@bbum no es el 'object_getInstanceVariable' sugerido en la otra respuesta relativamente inocuo? –

5

Usted no debe realmente, pero el acceso es como un puntero a un miembro de una estructura:

-(NSMutableArray *)displayedItems { 
    return self->_displayedItems; 
} 

Esto es algo frágil que hacer, como estoy seguro de que está consciente sin embargo;)

ACTUALIZACIÓN: Ya que has mencionado lo anterior no funciona, trate de descender al tiempo de ejecución:

-(NSMutableArray *)displayedItems { 
     NSMutableArray *displayedItems; 
     object_getInstanceVariable(self, "_displayedItems", (void *)&displayedItems); 
     return displayedItems; 
} 

(Probado, funciona)

+0

Esto tampoco funciona, da un error idéntico. ¡Gracias por la sugerencia, sin embargo! – vilhalmer

+0

Hmm, d'oh! Ver mi actualización – d11wtq

+3

Esa es una respuesta técnicamente correcta, pero no es una respuesta moralmente correcta: p – Yuji

Cuestiones relacionadas