Wann wird selbst für Klasseneigenschaften benötigt? Zum Beispiel:
%Vor%vs
%Vor%MyProperty ist ein NSString, der als (nichtatomare, Kopie) festgelegt ist. Gibt es einen Unterschied in der Speicherverwaltung für die beiden oben genannten?
Was ist, wenn es keine Eigenschaft gibt und die Variable MyProperty in der Header-Datei deklariert ist? Wird eine Eigenschaft benötigt, wenn sie nie außerhalb der Klasse referenziert wird? Macht es einen Unterschied für die Speicherverwaltung?
Ja, es gibt einen Unterschied für Speicher und Leistung.
%Vor%Dies wird als direkte Zuweisung betrachtet. Es gibt praktisch keinen Speicher- oder Leistungseinfluss. Das heißt natürlich nicht, dass es die beste Vorgehensweise ist - das ist eine andere Frage:)
%Vor%Diese Aussage hat erhebliche Auswirkungen auf Speicher und Leistung. Dies entspricht im Wesentlichen:
%Vor%Der alte Wert wird freigegeben und der neue Wert wird in MyProperty kopiert. Dies ist akzeptabel und besonders typisch im Umgang mit Strings, wenn die zuweisbare Zeichenfolge veränderbar ist (dh, sie könnte sich später ändern).
Wenn Sie, wie in Ihrem Beispiel, einfach eine statische Zeichenfolge (@ "hi there") zuweisen, ist es nicht falsch, den Zeichenfolgenwert direkt zuzuweisen. es ist effizienter, aber der Unterschied in der Leistung ist trivial.
Sie können eine Eigenschaft mit @property als retain, copy oder assign deklarieren (Standard ist assign). Sie können dann "accessor" (Getter / Setter) -Methoden erzeugen, indem Sie @synthesize verwenden. Hier sehen Sie, wie die Setter-Methoden aussehen, wenn Sie dies tun:
%Vor%Weitere Informationen finden Sie unter ObjectiveC deklarierte Eigenschaften .
"Sie können die @ synthesize- und @dynamic-Direktiven in @implementation-Blöcken verwenden, um bestimmte Compiler-Aktionen auszulösen. Beachten Sie, dass beides für eine bestimmte @property-Deklaration nicht erforderlich ist.
Wichtig: Wenn Sie für eine bestimmte Eigenschaft weder @synthesize noch @dynamic angeben, müssen Sie für diese Eigenschaft eine Getter- und Setter-Implementierung (oder nur eine Get-Eigenschaft) bereitstellen. "
Mit anderen Worten, wenn Sie eine Eigenschaft deklarieren, aber die Eigenschaft nicht synthetisieren, können Sie [self MyProperty] oder self.MyProperty nicht verwenden, wenn Sie die Methoden 'MyProperty' und 'setMyProperty' nicht definieren. Wenn Sie keine Eigenschaft deklarieren, haben Sie einfach eine Instanzvariable.
Hinweis: @dynamic generiert die Accessoren nicht. Es wird wirklich verwendet, wenn Sie Accessormethoden dynamisch (dh magisch) über Ladecode oder dynamische Methodenauflösung auflösen.
Der Unterschied ist, dass
%Vor%ist ein Punktnotationsaufruf, der den generierten Accessor aufruft, der die Retain-Zählungen korrekt behandelt (entspricht [self setMyProperty: @ "hi there"]), während
%Vor%ist eine direkte Zuweisung an Ihre Membervariable, die den alten Wert nicht freigibt, den neuen Wert beibehält oder irgendetwas anderes tut, was Ihr Accessor tut (zB wenn Sie einen benutzerdefinierten Setter haben, der zusätzliche Arbeit leistet).
Also, es gibt einen großen Unterschied in der Speicherverwaltung und im allgemeinen Verhalten zwischen den beiden. Die letztere Form ist fast immer falsch, es sei denn, Sie wissen genau, warum Sie es tun und dass Sie die Retain-Zählungen selbst richtig handhaben.
Wenn Sie automatische Key verwenden -Value Observing (oder jede Cocoa-Technologie, die darauf aufbaut - wie Bindungen, ...), es ist auch wichtig, den Setter zu verwenden. Der Beobachter erhält keine Benachrichtigung, wenn Sie ihn dem Ivar zuweisen. Wenn Sie "MyProperty" an ein NSTextfield binden und den "MyProperty" -Ivar über Code ändern, zeigt das gebundene Textfeld immer noch den alten Wert an, da es keine Änderungsbenachrichtigung erhalten hat.
Um auf eine Variable zugreifen zu können, ist es oft nicht nötig, die Punktnotation zu verwenden. In Code, der von den XCode-Vorlagen generiert wird, sehen Sie beispielsweise Folgendes:
%Vor%Es ist nicht notwendig, hier self.flipsideViewController zu schreiben, weil die Accessor-Methode normalerweise nichts anderes tut, als die Variable zu übergeben.
Eine gute Faustregel ist also, die Punktnotation zu verwenden, wenn Sie eine Variable setzen (absolut notwendig, es sei denn, Sie wollen selbst halten und freigeben), aber nicht, wenn Sie Zugriff auf es:
%Vor%Wenn Sie Nicht-Objekttypen wie int oder float oder viele andere verwenden, können Sie die Punktnotation / Setter-Methode nicht verwenden. In diesen Fällen gibt es nichts zu behalten, daher wird die Setter-Methode wenig tun, außer nur den Wert zuzuweisen.
Jedoch machen synthetisierte Getter und Setter mehr als nur das Speichern und Freigeben. Wie andere bereits erwähnt haben, sind sie auch der Motor, der das KVO-System am Laufen hält. Daher sollten Sie die richtigen Setter auch für Ints, Floats und den Rest verwenden.
Was ist mit den Accessoren? In komplexeren Kontexten reagiert eine Klasse möglicherweise auf eine Anforderung für den Wert einer Variablen , auch wenn die Variable nicht existiert . Um das erhabene Objective-C-Handbuch zu zitieren, könnten Klassen "Methodenimplementierungen direkt oder zur Laufzeit bereitstellen, die andere Mechanismen [als einfache Zugriffsmethoden] verwenden, wie dynamisches Laden von Code oder dynamische Methodenauflösung."
(Eine Möglichkeit, diese Art von spontaner Antwort auf Nachrichten zu implementieren, besteht darin, NSObject-Methoden wie methodSignatureForSelector: und forwardInvocation:.) zu überschreiben.
Aus diesem Grund ist die Verwendung ordnungsgemäß deklarierter Schnittstellen (ob synthetisiert oder nicht) immer eine gute Idee, wenn Sie an etwas Großem arbeiten. Aber es ist völlig in Ordnung, direkt auf Ivars zuzugreifen, solange Sie sie mit der richtigen API setzen .
(Hinweis: Ich bin kein Cocoa-Guru, daher sind Korrekturen mehr als willkommen.)
Für den zweiten Teil der Frage wird die Definition der Eigenschaften nicht benötigt, es ist eine Hilfe für uns. Die @ synthesize-Anweisung für die Eigenschaft generiert Zugriffsmethoden für Eigenschaften, sodass wir sie nicht manuell ausführen müssen, und zwar:
Dieser Code weist den Compiler an Generieren oder Synthetisieren des Accessors Methoden. Der Compiler wird generieren die Accessor-Methoden mit gut getestete, schnelle Algorithmen, die sind bereit für Multi-Core und Multi-Threaded-Umgebungen, einschließlich Sperren von Variablen in Setter-Methoden. Nicht nur die Verwendung von Eigenschaften reduziert die Menge an Code, die Sie haben müssen schreiben, ersetzt er diesen Code mit dem bestmögliche Accessoren für den heutigen Tag moderne Multicore-Systeme. Später, wenn Sie müssen eine Alternative bereitstellen Implementierung für eine Immobilie Accessor, können Sie einfach hinzufügen geeigneten Code für Ihre Klasse.
Das nonatomic
verhindert die Verwendung von Sperren beim Zugriff auf Variablen. Wenn Sie nichts angeben, ist der Standardwert atomic
. Sperren ist nützlich auf Multithread-Systemen. Die Kopie gibt an, welcher Code für Accessoren generiert werden soll, copy
kopiert das Objekt, retain
behält neues Objekt und gibt altes wieder frei, assign
ist gut für einfache Variablen wie int, um einfach Werte zuzuweisen.
Wenn Sie also Ihre Eigenschaft wie oben in (nonatomic,copy)
definieren und dann self.MyProperty = @"Hey"
verwenden, rufen Sie einen generierten Accessor auf, der eine Kopie der neuen Variablen erstellt und nicht nur zuweist. Sie können Accessor überschreiben und die Überprüfung hinzufügen.
Aufgrund der obigen Ausführungen würde ich sagen, dass das Definieren von Eigenschaften auch dann Vorteile hat, wenn die Variable nicht außerhalb der Klasse verwendet wird.
Ich glaube, um auf Eigenschaften zugreifen zu können, sollten Sie self.MyProperty
statt nur MyProperty
verwenden, aber ich kann Ihnen nicht erklären, warum.
Könnte etwas mit der Tatsache zu tun haben, dass der Compiler von
das:
%Vor%Aber ich spekuliere nur hier.
Unabhängig davon, ob Sie self.MyProperty oder MyProperty aufrufen, sollte dies die Speicherverwaltung nicht beeinflussen (ich würde immer noch die erste - self.MyProperty bevorzugen).
Siehe Objective-C 2.0 Übersicht für eine Beschreibung auf hoher Ebene von Apple.
Das ist eine alte Frage, obwohl es früher "Wann schreibe ich [self setMyProperty:@"hi there"]
?" (Beachten Sie, dass self.MyProperty = @"hi there"
genau dem entspricht.)
Die Antwort, die ich immer gehört habe (und was sinnvoll ist) ist, dass immer den Accessor verwendet; nie schreiben MyProperty = @"hi there"
. Dafür gibt es mehrere Gründe:
MyProperty
einen bestimmten Nebeneffekt haben muss, können Sie die Setter-Methode hinzufügen, ohne jedes Mal zu finden, wenn Sie MyProperty
. MyProperty
haben, ist es einfach, dem Setter (oder sogar Getter) Logging-Code hinzuzufügen, um jedes Mal herauszufinden, wenn er geändert (oder sogar zugegriffen) wird. Zusammenfassung: Es ist am sichersten und am flexibelsten, immer [self setMyProperty:@"hi there"]
oder self.MyProperty = @"hi there"
zu verwenden, und niemals MyProperty = @"hi there"
.
Immer noch nicht klar, wann die Accessoren zu verwenden sind und wann eine direkte Zuweisung auf Ivars möglich ist? Ich habe viele Apple-Beispiele gesehen, die direkt auf die Ivars zugreifen. Die Verwendung von Eigenschaften für alle Ivars scheint pedantischer Overkill zu sein.
Es scheint, dass nur signifikante Ivars, die länger herum sein müssen und außerhalb zugegriffen werden, dazu tendieren, die Eigenschaften zu verwenden.
Würde es einigen Kakao-Gurus empfehlen, einzusteigen und zu klären.
Tags und Links objective-c