2010-12-13 10 views
10

EDIT: Ich werde das nicht tun, ich weiß jetzt, wie gefährlich das sein kann. Aber die Frage bleibt für rein akademische Zwecke.Zugriff auf private Variable in der Kategorie resultiert in Linker-Fehler

Ich versuche, eine Kategorie in NSCollectionView zu implementieren, die mich auf die private Variable _displayedItems zugreifen lassen wird. Ich muss in meiner Unterklasse darauf zugreifen können. Also, ich habe die folgende Kategorie erstellt:

... was scheint, als sollte es perfekt funktionieren. Allerdings, wenn ich versuche, dies zu kompilieren, der Linker gibt mir die folgende Fehlermeldung:

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 

ich für eine Tatsache, dass _displayedItems in NSCollectionView existiert, habe ich an der Schnittstelle geschaut und auch gedruckt es Inhalt ist mit gdb. Kennt jemand eine Möglichkeit, das zu beheben?

Vielen Dank im Voraus!
Billy

+0

Ich fand dies die beste Antwort. Einfach, einfach und sicher: http: // stackoverflow.com/questions/16678463/Zugriff auf eine Methode in einer Super-Klasse-wenn-es-nicht-exposed –

Antwort

12

_displayedItems ist ein privater Ivar, also sollten Sie nicht darauf zugreifen, auch nicht aus einer Kategorie.

Das heißt, sollten Sie versuchen, den gleichen Code mit

gcc -arch i386 

und

gcc -arch x86_64 

und sehen Sie den Unterschied zu kompilieren. Im 32-Bit-Modus sehen Sie den Fehler nicht. Dies zeigt, wie fragil die Situation ist. Das solltest du wirklich nicht.

Das heißt, es gibt eine Möglichkeit, dass Ivar KVC durch Missbrauch zu bekommen:

@implementation NSCollectionView (displayedItems) 

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

@end 

Beachten Sie, dass Ihre Methode als displayedItems nur nennen sollte nicht. Das würde eine Endlosschleife bilden, weil die KVC-Maschinerie Ihre Methode früher finden würde als der Ivar. Siehe here.

Oder Sie können auf alle versteckten Ivar mit Objective-C Laufzeitfunktionen zugreifen. Das macht auch Spaß.

Lassen Sie mich jedoch noch einmal sagen. Es ist ein großer Unterschied, zu wissen, dass man eine Sache machen und diese Sache wirklich tun kann. Denken Sie nur an irgendein schreckliches Verbrechen. und das selbst zu tun.

TUN SIE DAS NICHT !!!!!

+0

Okay, ich verstehe es, schlechte Idee. :) Danke trotzdem! – vilhalmer

+1

Ich würde das "Do not do that" nach oben verschieben. :) Wenn Sie anfangen, sich mit dem internen Zustand von Framework-Klassen zu beschäftigen, werden Sie sicher von Abstürzen und mysteriösen Fehlern im Laufe der Zeit überrascht sein. – bbum

+0

@bbum ist nicht die 'object_getInstanceVariable' in der anderen Antwort relativ harmlos vorgeschlagen? –

5

Sie sollten nicht wirklich, aber es Zugang wie ein Zeiger auf ein Element einer Struktur:

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

Dies ist eine zerbrechliche Sache zu tun, wie ich bin sicher, dass Sie sich bewusst sind jedoch;)

UPDATE: Da Sie die oben erwähnt haben nicht funktioniert, versuchen Sie, die Laufzeit herunterfallen:

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

(getestet arbeitet)

+0

Dies funktioniert auch nicht, es gibt einen identischen Fehler. Danke für den Vorschlag! – vilhalmer

+0

Hmm, oh! Siehe mein Update. – d11wtq

+3

Das ist eine technisch korrekte Antwort, aber keine moralisch korrekte Antwort: p – Yuji