2010-12-13 63 views
10

EDIT: Je ne vais pas faire cela, je réalise maintenant à quel point cela peut être dangereux. Mais, la question reste à des fins purement académiques.L'accès à une variable privée dans la catégorie entraîne une erreur de lien

J'essaie d'implémenter une catégorie sur NSCollectionView qui me permettra d'accéder à la variable privée _displayedItems. Je dois pouvoir y accéder dans ma sous-classe. Donc, j'ai créé la catégorie suivante:

@interface NSCollectionView (displayedItems) 

- (NSMutableArray *)displayedItems; 

@end 


@implementation NSCollectionView (displayedItems) 

- (NSMutableArray *)displayedItems 
{ 
    return _displayedItems; 
} 

@end 

... ce qui semble fonctionner parfaitement. Cependant, lorsque je tente de compiler cela, l'éditeur de liens me donne l'erreur suivante:

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 

Je sais pertinemment que _displayedItems existe dans NSCollectionView, je l'ai regardé l'interface et aussi imprimé son contenu en utilisant gdb. Est-ce que quelqu'un sait d'un moyen de résoudre ce problème?

Merci d'avance!
Billy

+0

J'ai trouvé que c'était la meilleure réponse. Facile, simple et sûr: http: // stackoverflow.com/questions/16678463/access-a-method-in-a-super-class-when-its-not-exposed –

Répondre

12

_displayedItems est un ivar privé, vous ne devriez donc pas y accéder, même à partir d'une catégorie.

Cela dit, vous devriez essayer de compiler le même code avec

gcc -arch i386 

et

gcc -arch x86_64 

et voir la différence. En mode 32 bits, vous ne voyez pas l'erreur. Cela montre à quel point la situation est fragile. Tu ne devrais vraiment pas.

Cela dit, il y a un moyen d'obtenir que Ivar en abusant KVC:

@implementation NSCollectionView (displayedItems) 

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

@end 

Notez que vous ne devriez pas le nom de votre méthode comme displayedItems. Cela ferait une boucle infinie, parce que la machinerie KVC trouverait votre méthode plus tôt que l'ivar. Voir here.

Ou vous pouvez accéder à n'importe quel ivar caché en utilisant les fonctions d'exécution Objective-C. C'est aussi amusant.

Toutefois, permettez-moi de le répéter. Il y a une grande différence dans le fait de savoir que vous pouvez faire une chose et faire cette chose pour de vrai. Pensez juste à un crime hideux. et faire cela par vous-même.

NE FAITES PAS CELA !!!!!

+0

Très bien, je comprends, mauvaise idée. :) Merci quand même! – vilhalmer

+1

Je déplacerais le "ne fais pas ça" vers le haut. :) Si vous commencez à déblatérer avec l'état interne des classes de framework, vous êtes sûr d'être surpris par des crashs et des échecs mystérieux au fil du temps. – bbum

+0

@bbum n'est pas le 'object_getInstanceVariable' suggéré dans l'autre réponse relativement inoffensif? –

5

Vous ne devriez pas vraiment, mais l'accès comme un pointeur sur un membre d'une struct:

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

Ceci est une chose fragile à faire, comme je suis sûr que vous êtes au courant cependant;)

MISE à JOUR: Comme vous l'avez mentionné le dessus ne fonctionne pas, essayez de descendre à l'exécution:

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

(Testé, fonctionne)

+0

Cela ne marche pas non plus, cela donne une erreur identique. Merci pour la suggestion, cependant! – vilhalmer

+0

Hmm, d'oh! Voir ma mise à jour – d11wtq

+3

C'est une réponse techniquement correcte, mais pas une réponse moralement correcte: p – Yuji