Obj-C Speicherverwaltung
Die Speicherverwaltung ist einer der wichtigsten Prozesse in jeder Programmiersprache. Dies ist der Prozess, bei dem der Speicher von Objekten zugewiesen wird, wenn sie benötigt werden, und freigegeben wird, wenn sie nicht mehr benötigt werden.
Das Verwalten des Objektspeichers ist eine Frage der Leistung. Wenn eine Anwendung nicht benötigte Objekte nicht freigibt, wächst ihr Speicherbedarf und die Leistung leidet.
Objective-C-Speicherverwaltungstechniken können grob in zwei Typen eingeteilt werden.
- "Manual Retain-Release" oder MRR
- "Automatische Referenzzählung" oder ARC
"Manual Retain-Release" oder MRR
In der MRR verwalten wir den Speicher explizit, indem wir Objekte selbst verfolgen. Dies wird mithilfe eines Modells implementiert, das als Referenzzählung bezeichnet wird und das die Foundation-Klasse NSObject in Verbindung mit der Laufzeitumgebung bereitstellt.
Der einzige Unterschied zwischen MRR und ARC besteht darin, dass die Aufbewahrung und Freigabe in ersterem von uns manuell erfolgt, während sie in letzterem automatisch erledigt wird.
Die folgende Abbildung zeigt ein Beispiel für die Funktionsweise der Speicherverwaltung in Objective-C.
Der Speicherlebenszyklus des Objekts der Klasse A ist in der obigen Abbildung dargestellt. Wie Sie sehen können, wird die Aufbewahrungsanzahl unter dem Objekt angezeigt. Wenn die Aufbewahrungsanzahl eines Objekts 0 wird, wird das Objekt vollständig freigegeben und sein Speicher wird für andere Objekte freigegeben.
Das Objekt der Klasse A wird zuerst mit der in NSObject verfügbaren Methode alloc / init erstellt. Jetzt wird die Anzahl der Einbehaltungen 1.
Jetzt behält Klasse B das Objekt der Klasse A bei und die Anzahl der Objekte der Klasse A wird 2.
Dann erstellt Klasse C eine Kopie des Objekts. Jetzt wird es als eine weitere Instanz der Klasse A mit denselben Werten für die Instanzvariablen erstellt. Hier ist die Aufbewahrungszahl 1 und nicht die Aufbewahrungszahl des ursprünglichen Objekts. Dies wird durch die gepunktete Linie in der Figur dargestellt.
Das kopierte Objekt wird von der Klasse C unter Verwendung der Freigabemethode freigegeben, und die Aufbewahrungsanzahl wird 0, und daher wird das Objekt zerstört.
Im Fall des anfänglichen Objekts der Klasse A beträgt die Anzahl der Zurückbehaltungen 2 und es muss zweimal freigegeben werden, damit es zerstört wird. Dies erfolgt durch Release-Anweisungen der Klassen A und B, die den Retentionszähler auf 1 bzw. 0 verringern. Schließlich wird das Objekt zerstört.
MRR-Grundregeln
Wir besitzen jedes Objekt, das wir erstellen: Wir erstellen ein Objekt mit einer Methode, deren Name mit "alloc", "new", "copy" oder "mutableCopy" beginnt.
Wir können das Eigentum an einem Objekt übernehmen, indem wir behalten: Ein empfangenes Objekt bleibt normalerweise innerhalb der Methode, in der es empfangen wurde, gültig, und diese Methode kann das Objekt auch sicher an seinen Aufrufer zurückgeben. Wir verwenden Retain in zwei Situationen -
Bei der Implementierung einer Accessor-Methode oder einer Init-Methode möchten wir den Besitz eines Objekts übernehmen, das als Eigenschaftswert gespeichert werden soll.
Um zu verhindern, dass ein Objekt als Nebeneffekt einer anderen Operation ungültig wird.
Wenn wir es nicht mehr benötigen, müssen wir das Eigentum an einem Objekt, das wir besitzen, aufgeben: Wir geben das Eigentum an einem Objekt auf, indem wir ihm eine Freigabemeldung oder eine Autorelease-Nachricht senden. In der Kakao-Terminologie wird das Aufgeben des Eigentums an einem Objekt daher typischerweise als "Freigeben" eines Objekts bezeichnet.
Sie dürfen das Eigentum an einem Objekt, das Sie nicht besitzen, nicht aufgeben: Dies ist nur eine Folge der zuvor ausdrücklich festgelegten Richtlinienregeln.
#import <Foundation/Foundation.h>
@interface SampleClass:NSObject
- (void)sampleMethod;
@end
@implementation SampleClass
- (void)sampleMethod {
NSLog(@"Hello, World! \n");
}
- (void)dealloc {
NSLog(@"Object deallocated");
[super dealloc];
}
@end
int main() {
/* my first program in Objective-C */
SampleClass *sampleClass = [[SampleClass alloc]init];
[sampleClass sampleMethod];
NSLog(@"Retain Count after initial allocation: %d",
[sampleClass retainCount]);
[sampleClass retain];
NSLog(@"Retain Count after retain: %d", [sampleClass retainCount]);
[sampleClass release];
NSLog(@"Retain Count after release: %d", [sampleClass retainCount]);
[sampleClass release];
NSLog(@"SampleClass dealloc will be called before this");
// Should set the object to nil
sampleClass = nil;
return 0;
}
Wenn wir das obige Programm kompilieren, erhalten wir die folgende Ausgabe.
2013-09-28 04:39:52.310 demo[8385] Hello, World!
2013-09-28 04:39:52.311 demo[8385] Retain Count after initial allocation: 1
2013-09-28 04:39:52.311 demo[8385] Retain Count after retain: 2
2013-09-28 04:39:52.311 demo[8385] Retain Count after release: 1
2013-09-28 04:39:52.311 demo[8385] Object deallocated
2013-09-28 04:39:52.311 demo[8385] SampleClass dealloc will be called before this
"Automatische Referenzzählung" oder ARC
Bei der automatischen Referenzzählung oder ARC verwendet das System dasselbe Referenzzählsystem wie die MRR, fügt jedoch zur Kompilierungszeit die entsprechenden Speicherverwaltungsmethodenaufrufe ein, die für uns erforderlich sind. Wir empfehlen dringend, ARC für neue Projekte zu verwenden. Wenn wir ARC verwenden, ist es normalerweise nicht erforderlich, die in diesem Dokument beschriebene zugrunde liegende Implementierung zu verstehen, obwohl dies in einigen Situationen hilfreich sein kann. Weitere Informationen zu ARC finden Sie in den Versionshinweisen zu ARC.
Wie oben erwähnt, müssen wir in ARC keine Release- und Retain-Methoden hinzufügen, da dies vom Compiler erledigt wird. Tatsächlich ist der zugrunde liegende Prozess von Objective-C immer noch der gleiche. Es verwendet die Aufbewahrungs- und Freigabevorgänge intern, um dem Entwickler das Codieren zu erleichtern, ohne sich um diese Vorgänge kümmern zu müssen, wodurch sowohl die Menge des geschriebenen Codes als auch die Möglichkeit von Speicherverlusten verringert werden.
Es gab ein anderes Prinzip namens Garbage Collection, das in Mac OS-X zusammen mit MRR verwendet wird, aber seit seiner Ablehnung in OS-X Mountain Lion wurde es nicht zusammen mit MRR diskutiert. Außerdem hatten iOS-Objekte nie eine Speicherbereinigungsfunktion. Und mit ARC wird die Garbage Collection auch in OS-X nicht verwendet.
Hier ist ein einfaches ARC-Beispiel. Beachten Sie, dass dies auf dem Online-Compiler nicht funktioniert, da ARC nicht unterstützt wird.
#import <Foundation/Foundation.h>
@interface SampleClass:NSObject
- (void)sampleMethod;
@end
@implementation SampleClass
- (void)sampleMethod {
NSLog(@"Hello, World! \n");
}
- (void)dealloc {
NSLog(@"Object deallocated");
}
@end
int main() {
/* my first program in Objective-C */
@autoreleasepool {
SampleClass *sampleClass = [[SampleClass alloc]init];
[sampleClass sampleMethod];
sampleClass = nil;
}
return 0;
}
Wenn wir das obige Programm kompilieren, erhalten wir die folgende Ausgabe.
2013-09-28 04:45:47.310 demo[8385] Hello, World!
2013-09-28 04:45:47.311 demo[8385] Object deallocated