2010-11-24 9 views
26

Ich bin mit objective-c-Eigenschaften festgefahren. Was ich brauche, ist eine schreibgeschützte Eigenschaft für eine Variable zuzuweisen, genau das Gegenteil von readonly, d. H. Die Variable kann setMethod haben, aber sie sollte getMethod nicht haben. Ich weiß nicht, wie ich es machen soll. Antworten mit einigen Code-Schnipsel sind willkommen.Nur Objekt in Objective-C schreiben

+2

Was ist die schreibgeschützte Eigenschaft? IMHO ist es nur eine Verschwendung von Erinnerung. – Eimantas

+20

Viele Verwendungen; Wenn Sie möchten, dass etwas öffentlich nur schreibgeschützt ist und intern der Klasse entspricht, wird es readwrite geschrieben. – bbum

+0

Wenn eine externe Klasse eine Variable kennt, die übergeben werden muss, aber keinen Grund hat, zu wissen, wofür sie gerade eingestellt ist. – ArtOfWarfare

Antwort

11

Sie können wie etwas tun:

@interface MyClass { 
@private 
int _var; 
} 

- (void)setVar:(int)newVar; 
@end 

@implementation MyClass 
- (void)setVar:(int)newVar { 
_var = newVar; 
} 
@end 

Jetzt können Sie die Variable var wie eine Eigenschaft zuzugreifen, ist nur für schreiben:

@implementation SomeOtherClass 
... 
MyClass c = [[MyClass alloc] init]; 
c.var = 3; 
... 
@end 

Und wenn Sie versuchen, die gefälschte Eigenschaft lesen die Compiler wird dich warnen.

+1

Sie müssen eine Methode definieren '- (void) setVar: (int) newVar' in der Implementierung sowie die Schnittstelle. – JeremyP

+0

Beachten Sie, dass dies den Wert nicht vollständig verdeckt. Wenn Sie nicht (BOOL) accessInstanceVariablesDirectly mit NO überschreiben, können Sie den Wert mit valueForKey abrufen: @ "var". Und selbst wenn Sie dies überschreiben, können Sie den Wert immer noch mit einer objC-Laufzeitmethode wie object_getInstanceVariable erhalten. –

+4

es ist keine Eigenschaft – kubbing

5

Gibt es einen Grund, dass dies eine Eigenschaft sein muss? Ich würde den Setter einfach als eine Methode deklarieren und die normale Syntax [foo setVar:bar] verwenden.

+5

Oder verwenden Sie die Punktsyntax ... 'foo.var = bar;' wird immer noch funktionieren. – bbum

+0

Ja, das funktioniert, aber xCode scheint var bei der Eingabe nicht automatisch zu vervollständigen. –

+0

@ FredrikJohansson du hast Recht. Für eine Auto-Vervollständigung-freundliche Lösung, möchten Sie vielleicht meine Lösung auschecken. –

44

Ein weiterer gültiger Ansatz ist die normale Eigenschaft zu erklären und den Getter nicht verfügbar

@interface MyClass 
@property NSString * var; 
- (NSString *)var UNAVAILABLE_ATTRIBUTE; 
@end 

Diese machen einen Fehler bei der Kompilierung in Fall erhöht jemand den Getter zuzugreifen versucht.


Der Hauptvorteil dieses Ansatzes ist, dass Sie tatsächlich eine Immobilien TM und nicht ein Ersatz durch eine Instanzvariable und einen Setter gefälscht haben, was das bedeutet: Sie

  • Wenn die Punktnotation in Xcode
  • automatisch vervollständigt wird, funktionieren alle Laufzeitfunktionen wie class_getProperty und class_copyPropertyList wie erwartet.

Das heißt, wird der Getter Implementierung ohnehin synthetisiert und es könnte etwas mit wie

NSString * string = [myObj performSelector:@selector(var)]; 

oder mit NSInvocation (im Falle einer Nicht-id Eigenschaft)

Wenn Sie aufgerufen werden, sind paranoid und Sie wirklich wollen, dass der Client den Getter aufrufen, können Sie explizit eine Ausnahme durch die Bereitstellung Ihrer eigenen Implementierung zu werfen.

@implementation MyClass 
- (int)var { 
    [NSException raise:NSInternalInconsistencyException 
       format:@"property is write-only"]; 
} 
@end 

Wie auch immer, wenn jemand ernsthaft mit Ihrer Instanz Variable manipulieren will, können sie die Laufzeit verwenden, darauf zuzugreifen, so dass die letzte Vorsichtsmaßnahme wahrscheinlich nutzlos ist der Anwendungsfall gegeben. Ein Kompilierungsfehler ist das, was Sie wirklich suchen.

+0

ist es für LLVM verfügbar? – Mingming

+0

Dies sollte die akzeptierte Antwort sein. – braden