2014-04-24 10 views
5

Ich habe Klasse A mit einem Header, der etwa wie folgt aussieht:Einstellwerte in einer benutzerdefinierten Struktur als Eigenschaft in Objective-C

typedef struct { 
    int x; 
    int y; 
} Position; 

@interface ClassA : NSObject 

@property Position currentPosition; 

@end 

Und ich versuche, von der Eigenschaft einzelne Werte der Position Struktur zuweisen in eine andere Klasse wie folgt:

ClassA * classA = [ClassA new]; 
classA.currentPosition.x = 10; 

, die einen Fehler gibt „Ausdruck ist nicht übertragbar“ und wird nicht kompiliert.

Ich kann es wie folgt festgelegt:

ClassA * classA = [ClassA new]; 
Position position = { 
    .x = 1, 
    .y = 2 
}; 

classA.currentPosition = position; 

Und ich kann sogar einzelne „Eigenschaften“ von position Variable wie folgt ändern:

ClassA * classA = [ClassA new]; 
Position position = { 
    .x = 1, 
    .y = 2 
}; 

// WORKS 
position.x = 4;  

// DOESN'T WORK 
// classA.currentPosition.x = 4; 

classA.currentPosition = position; 

Warum kann ich keine Werte einzeln sie, wenn sind eine Eigenschaft?

+0

Wenn Sie typedef verwendet haben, müssen Sie in der @ property-Deklaration nicht 'struct' hinzufügen. –

+0

@NicolasMiari - Ich habe es korrigiert, ich habe verschiedene Arten der Erklärung versucht, ich habe nur die falschen Sachen kopiert. – Logan

+0

Siehe auch [Wie erhält man Zuweisungszugriff auf CGRect-Elemente, wenn das CGRect eine Instanz ist?] (Http://stackoverflow.com/q/5860755), obwohl es sich um eine vorab deklarierte Eigenschaft handelt. –

Antwort

6

Dieser Ausdruck:

classA.currentPosition 

gibt eine temporäre Kopie der Struktur, nicht die Struktur selbst. Der Compiler-Fehler weist Sie darauf hin, dass Sie einem Mitglied dieser temporären Kopie keinen Wert zuweisen können (da es technisch eine rvalue ist). Aber Sie möchten diesem Member sowieso keinen Wert zuweisen, weil er mit der Struktur selbst verschwindet.

Warum erhalten Sie nur eine Kopie der Struktur an erster Stelle?

Da

@property Position currentPosition 

ist eigentlich nur für Kurzschrift:

-(Position)currentPosition; 
-(void)setCurrentPosition(Position value); 

und in C-Familie Spricht, die erste Zeile (die Getter) zeigt an, dass es durch-Wert eine Position Struktur ist die Rückkehr oder als Kopie.

Sie könnten Ihren eigenen Accessor erstellen, der eine Referenz zurückgibt, aber Sie sollten es wahrscheinlich nicht tun. Dies ist kein allgemeines Idiom in Objective-C - zumindest nicht in diesem Zusammenhang - und Sie sollten generell versuchen, bei den gängigen Idiomen für eine Sprache zu bleiben.

Stattdessen sollten Sie die Position wie folgt verwenden;

Position pos = classA.position; 
pos.x = 4; 
classA.position = pos; 

Schließlich, wenn Sie wirklich in der Lage sein wollen current, um den Syntax Sie ursprünglich gewünscht, während Objective-C Idiome maintaing, könnten Sie einfach eine Klasse machen Position eher als eine Struktur. Dann kann die Eigenschaft Position * zurückgeben und der Rest der Syntax würde funktionieren. Stellen Sie sicher, den Zeiger in Ihrer init Funktion (oder wenn zutreffend) zu initialisieren.

+1

Dies scheint meine Frage zu beantworten, aber ich bin neugierig, warum es einen Downvote bekommen hat? Gibt es etwas, das dies falsch macht? – Logan

+0

Sie benötigen jedes Mal 3 Zeilen, wenn Sie eine der Eigenschaften in der Struktur zuweisen möchten. Es klont Ihre Struktur jedes Mal, wenn Sie darauf zugreifen. Wenn Sie also keine Eigenschaften zuweisen, erstellen Sie ständig neue Instanzen dieser Struktur mit unterschiedlichen Werten. – manecosta

2

Eigenschaften funktionieren nicht für C-Strukturen.

Sie können es tun:

@property Position *currentPosition; 

Grundsätzlich einen Zeiger verwenden.

Jetzt müssen Sie eigentlich diesen Zeiger initialisieren, so:

- (id) init { 
    self = [super init]; 
    if(self){ 
     self.currentPosition = malloc(sizeof(Position)); 
    } 
    return self; 
} 

Dann vergessen Sie nicht, Pfeil-Notation zu verwenden, da Sie mit einem Zeiger zu tun hat:

classA.currentPosition->x = 5; 

Und don Vergessen Sie nicht, die von Ihnen angeforderte Erinnerung zu löschen!

-(void)dealloc{ 
    free(self.currentPosition); 
} 
+1

Sie können dies tun (es ist gültig), aber Sie sollten nicht (es ist * nicht * idiomatisch). Es gibt bessere und objektivere Möglichkeiten, dasselbe zu tun. – adpalumbo

+0

Dies führt zu einem Fehler bei 'self.currentPosition = malloc (sizeof (Position));' - 'Zuweisen von' Position 'vom inkompatiblen Typ' void * '" – Logan

+2

Dieser Fehler bedeutet, dass Sie die Eigenschaftsdeklaration nicht geändert haben Zeiger, @Logan. –

Verwandte Themen