So erhalten Sie Zuweisungszugriff auf CGRect-Elemente, wenn CGRect eine Instanzvariable ist

7
%Vor%

Nach dem Erstellen einer Instanz von some_class:

%Vor%

Dies erzeugt einen "Ausdruck nicht zuweisbar" -Fehler.

Natürlich funktioniert das gut:

%Vor%

Ich schätze, das Problem besteht darin, dass der automatisch-magisch erzeugte Setter nur weiß, dass er CGRect "the_rect" zuweisen muss. OK, ich verstehe. Kann ich sagen, dass kein Setter erstellt werden soll, damit ich direkt auf die Membervariable zugreifen und Zuweisungen an die Strukturelemente vornehmen kann, ohne das gesamte CGRect zuweisen zu müssen?

Ich nehme an, dass ich das in vier individuelle CGFloats für Herkunft.x, Herkunft.y, Größe.Größe und Größe.Höhe zerlegen könnte ... aber Sie würden denken, dass es eine Möglichkeit geben würde, dies stattdessen mit CGRects zu tun .

Was verwirrend ist, ist, dass dies natürlich gut funktioniert:

%Vor%

Mit anderen Worten, der Getter weiß, wie er durch die Struktur navigieren und den Wert eines seiner Elemente herausziehen muss, damit ich ihn benutzen kann. Das Gegenteil scheint nicht der Fall zu sein, da man einfach nicht in einen ivar hineingreifen kann, der eine Struktur ist, und eine Zuweisung zu einem seiner Elemente vornehmen, ohne die gesamte Struktur zuordnen zu müssen.

Ich habe das auch versucht:

%Vor%

Nach der Instanziierung in einem anderen Modul:

%Vor%

... und es wurde ein Fehler ausgegeben, der besagt, dass das referenzierte Element kein Zeiger ist. Ich habe versucht, die Adresse von instance.the_rect ... aber das hat auch nicht funktioniert.

BEARBEITEN ZU KLARIFIZIEREN: Es geht darum, eine Klasse zu erstellen, die einige Ivars enthält, die zufällig Strukturen sind. Nachdem Sie die Klasse an einer anderen Stelle instanziiert haben, möchten Sie in der Lage sein, Zuordnungen zu den Struktur-IVAR-Elementen direkt vorzunehmen:

%Vor%

Ich benutze CGRect als ein praktisches Beispiel für eine bekannte Struktur, die man als Ivar verwenden könnte.

    
martin's 02.05.2011, 18:14
quelle

4 Antworten

6

Sie greifen generell nicht direkt von außerhalb der Klasse auf Membervariablen zu. Sie können es als @public deklarieren, wenn Sie wirklich möchten. Ich denke, Sie müssen möglicherweise Accessoren für jedes Mitglied der Rect erstellen:

%Vor%

und so weiter.

Das Problem ist, dass wenn Sie nach dem the_rect der Instanz fragen, Sie keinen Zeiger auf das gleiche rect bekommen, das die Instanz hat, als würden Sie, wenn der ivar ein Objektzeiger wäre - Sie erhalten eine neue Kopie der Struktur.

Es gibt ein paar Fragen, die sich um SO drehen, die dieses Problem diskutieren: 1 2 3

Öffentlicher ivar:

%Vor%

Zugriff:

%Vor%     
Josh Caswell 02.05.2011, 18:25
quelle
12

Sie wissen also wie um Ihr Problem zu umgehen, aber hier warum müssen Sie dies tun und einer der Gründe, warum Punkt-Syntax in Objective-C ist ein unheiliger Perversion:

anInstance.property = blah wird nach genau dem gleichen Code kompiliert, der erzeugt würde, wenn Sie stattdessen Folgendes eingegeben hätten: [anInstance setProperty:blah]

Dies funktioniert, wenn Ihre Eigenschaften nur Objekteigenschaften sind. Leider hat die Punktsyntax in C bereits eine nicht verwandte Bedeutung, und zwar auf Elemente einer Struktur zuzugreifen. dh Sie können Folgendes tun:

%Vor%

Wenn foo ein Objekt wäre, dann wäre foo.origin.x = 42 dasselbe wie [[foo origin] setX:42] (angenommen, dass origin auch ein Objekt wäre). Da es sich jedoch nur um Strukturen handelt, wird lediglich eine Offsetberechnung durchgeführt und der Wert im Speicher direkt festgelegt. Es gibt keine Methodenaufrufe.

Geben Sie die Punktsyntax in Objective-C ein. Jetzt haben wir zwei verschiedene Bedeutungen des Punktoperators (etwas, das nicht einmal C ++ erlaubt, ironischerweise, mit all seiner Operatorüberladung). Manchmal verwenden Sie es, um auf ein Strukturelement zuzugreifen. Manchmal verwenden Sie es, um einen Objektaccessor aufzurufen. Manchmal können Sie diese Anwendungen kombinieren. Manchmal können Sie nicht.

Sie können Member- und Accessor-Zugriff mischen und zuordnen, wenn der Ausdruck als R-Wert verwendet wird. Mit anderen Worten, Sie können Folgendes tun:

%Vor%

Wenn Sie dies jedoch als Lvalue versuchen, schlägt es fehl:

%Vor%

Der Weg, um dies zu umgehen, ist zu tun:

%Vor%

Natürlich, wenn Sie vergessen hätten, dass die Punktsyntax überhaupt existiert, dann haben Sie dieses Problem nie, weil der Versuch, einen Weg zu finden, dies mit der Bracketsyntax zu tun, nicht sinnvoll wäre.

Und das ist einer der vielen Gründe, warum ich die Punktsyntax für einen schrecklichen Fehler halte. Sie nie wären darüber verwirrt gewesen, wenn sie nie hinzugefügt worden wären.

    
Dave DeLong 02.05.2011 20:14
quelle
1

Sie können Elementen von struct nicht zuweisen. Dies müssen Sie stattdessen tun:

%Vor%

Indem Sie dies tun, ordnen Sie nicht den Elementen des rect zu, sondern stattdessen den gesamten rect-Wert.

    
Alexsander Akers 02.05.2011 18:58
quelle
0

Dies ist, wenn Sie eine statische Klassenvariable wollen, die ich jetzt weiß, was das OP nicht wollte.

Wenn Sie eine Klassenvariable wollen, glaube ich nicht, dass Sie das so machen. Ich habe gerade getestet, und der Wert wird nicht zwischen Elementen aufrechterhalten. Ich bin mir nicht sicher, warum es Ihnen erlaubt, leere Setter / Getter ohne Warnung zu synthetisieren.

Für eine Methode zum Erstellen von Klassenvariablen denke ich, dass es am besten ist, das static -Schlüsselwort zu verwenden, ähnlich wie in C. d.h.

%Vor%

Und dann initialisiere es in + (void)initalize . Sie müssen wahrscheinlich die Setter und Getter selbst schreiben.

    
Gustav Larsson 02.05.2011 18:29
quelle

Tags und Links