Es gibt zwei neue Speicherverwaltungsattribute für Eigenschaften, die von ARC eingeführt wurden: strong
und weak
.
Abgesehen von copy
, was offensichtlich etwas völlig anderes ist, gibt es Unterschiede zwischen strong
vs retain
und weak
vs assign
?
Nach meinem Verständnis besteht der einzige Unterschied darin, dass weak
dem Zeiger nil
zuweist, während assign
dies nicht tut, was bedeutet, dass das Programm abstürzt, wenn ich eine Nachricht sende auf den Zeiger, sobald er freigegeben wurde. Aber wenn ich weak
verwende, wird dies niemals passieren, da das Senden einer Nachricht an nil
nichts bewirkt.
Ich kenne keine Unterschiede zwischen strong
und retain
.
Gibt es einen Grund, warum ich assign
und retain
in neuen Projekten verwenden sollte, oder ist die Art, wie sie veraltet ist?
Aus dem Übergang zu ARC Release Notes (das Beispiel im Abschnitt über Eigenschaftsattribute).
// The following declaration is a synonym for: @property(retain) MyClass *myObject;
@property(strong) MyClass *myObject;
Also ist strong
dasselbe wie retain
in einer Eigenschaftsdeklaration.
Für ARC-Projekte würde ich strong
anstelle von retain
verwenden, assign
für C-Primitiveigenschaften und weak
für schwache Verweise auf Objective-C-Objekte.
Nachdem ich so viele Artikel über Stackoverflow-Posts und Demoanwendungen gelesen hatte, um die Attribute variabler Eigenschaften zu überprüfen, entschied ich mich, alle Attributinformationen zusammenzufassen:
Unten finden Sie den detaillierten Artikel-Link, auf dem Sie alle oben genannten Attribute finden, die Ihnen auf jeden Fall helfen werden. Vielen Dank an alle, die hier die besten Antworten geben !!
1. stark (iOS4 = behalten)
Beispiel:
@property (strong, nonatomic) ViewController *viewController;
@synthesize viewController;
2. schwach -
Beispiel
@property (weak, nonatomic) IBOutlet UIButton *myButton;
@synthesize myButton;
Starke und schwache Erklärung, Dank an BJ Homer :
Stellen Sie sich vor, unser Objekt ist ein Hund und der Hund möchte weglaufen (freigegeben werden).
Starke Zeiger sind wie eine Leine am Hund. Solange Sie die Leine am Hund haben, rennt der Hund nicht weg. Wenn fünf Personen ihre Leine an einem Hund befestigen (fünf starke Zeiger auf einen Gegenstand), rennt der Hund nicht davon, bis alle fünf Leinen gelöst sind.
Schwache Zeiger dagegen sind wie kleine Kinder, die auf den Hund zeigen und sagen: "Schau! Ein Hund!" Solange der Hund noch an der Leine ist, können die kleinen Kinder den Hund immer noch sehen und sie werden immer noch darauf zeigen. Sobald sich jedoch alle Leinen gelöst haben, rennt der Hund davon, egal wie viele kleine Kinder darauf zeigen.
Sobald der letzte starke Zeiger (Leine) nicht mehr auf ein Objekt zeigt, wird die Zuordnung des Objekts aufgehoben und alle schwachen Zeiger werden auf Null gesetzt.
Wann verwenden wir schwach?
Das einzige Mal, dass Sie schwach verwenden möchten, ist, wenn Sie Beibehaltungszyklen vermeiden möchten (z. B. behält der Elternteil das Kind und das Kind den Elternteil bei, sodass keines von beiden jemals freigegeben wird).
3.behalten = stark
Beispiel:
@property (nonatomic, retain) NSString *name;
@synthesize name;
4.zuweisen
Beispiel:
@property (nonatomic, assign) NSString *address;
@synthesize address;
Soweit ich weiß, sind strong
und retain
Synonyme, also tun sie genau das Gleiche .
Dann ist das weak
fast wie assign
, wird aber automatisch auf null gesetzt, nachdem das Objekt, auf das es zeigt, freigegeben wurde.
Das heißt, Sie können sie einfach ersetzen.
Allerdings, es gibt einen speziellen Fall, in dem ich assign
anstelle von weak
verwenden musste. Angenommen, wir haben zwei Eigenschaften delegateAssign
und delegateWeak
. In beiden ist unser Delegierter gespeichert, der uns durch die einzig starke Referenz besitzt. Der Delegierte gibt die Zuordnung auf, also ist unser -dealloc
Methode wird auch aufgerufen.
// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
[delegateWeak doSomething];
[delegateAssign doSomething];
}
Der Delegat befindet sich bereits im Freigabeprozess, ist jedoch noch nicht vollständig freigegeben. Das Problem ist, dass weak
Verweise auf ihn bereits ungültig sind! Eigenschaft delegateWeak
null enthält, aber delegateAssign
gültiges Objekt enthält (wobei alle Eigenschaften bereits freigegeben sind und ungültig gemacht, aber immer noch gültig).
// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
[delegateWeak doSomething]; // Does nothing, already nil.
[delegateAssign doSomething]; // Successful call.
}
Es ist ein ganz besonderer Fall, aber es zeigt uns, wie diese weak
-Variablen funktionieren und wann sie ungültig werden.
In Clangs Dokument zu Objective-C Automatic Reference Counting (ARC) werden die Besitzqualifizierer und -modifizierer klar erläutert:
Es gibt vier Besitzqualifikationsmerkmale:
- __ Autorelease
- __ stark
- __ * unsafe_unretained *
- __ schwach
Ein Typ ist nicht trivial eigentumsberechtigt, wenn er mit __ Autoreleasing, __ Stark oder __ Schwach qualifiziert ist.
Dann gibt es sechs Eigentumsmodifikatoren für deklarierte Eigenschaften:
- zuweisen impliziert __ * unsafe_unretained * Eigentum.
- copy impliziert __ strong Besitz sowie das übliche Verhalten der Kopiersemantik auf dem Setter.
- behalten impliziert __ stark Eigentum.
- stark impliziert __ stark Eigentum.
- * unsafe_unretained * impliziert __ * unsafe_unretained * Eigentum.
- schwach impliziert __ schwach Eigentum.
Mit Ausnahme von weak sind diese Modifikatoren in Nicht-ARC-Modi verfügbar.
Semantisch gesehen haben die Besitzqualifizierer in den fünf verwalteten Vorgängen eine unterschiedliche Bedeutung: Lesen, Zuweisen, Initialisieren, Zerstören und Verschieben, wobei wir dies meistens nur tun kümmern sich um den Unterschied in der Zuordnung Operation.
Zuweisung erfolgt bei der Auswertung eines Zuweisungsoperators. Die Semantik variiert je nach Qualifikation:
- Bei __ strong Objekten wird der neue Spitzenwert zuerst beibehalten. zweitens wird der Wert mit primitiver Semantik geladen; drittens wird der neue Spitzenwert mit primitiver Semantik in den lWert gespeichert; und schließlich wird der alte Spitzenreiter freigelassen. Dies wird nicht atomar durchgeführt; Die externe Synchronisierung muss verwendet werden, um diese Funktion bei gleichzeitigen Ladevorgängen und Speichern zu gewährleisten.
- Bei __ schwach Objekten wird der Wert so aktualisiert, dass er auf den neuen Spitzenwert zeigt, es sei denn, der neue Spitzenwert ist ein Objekt, das gerade einer Freigabe unterzogen wird. In diesem Fall wird der Wert auf einen Nullzeiger aktualisiert. Dies muss in Bezug auf andere Zuweisungen an das Objekt, das Lesen aus dem Objekt und die endgültige Freigabe des neuen Pointees atomar ausgeführt werden.
- Für __ * unsafe_unretained * -Objekte wird der neue Spitzenwert unter Verwendung primitiver Semantik in lvalue gespeichert.
- Bei __ autoreleasing Objekten wird der neue Pointee beibehalten, automatisch freigegeben und unter Verwendung der primitiven Semantik im Ivalue gespeichert.
Der andere Unterschied in Lesen, Init, Zerstören und Bewegen wird in Abschnitt 4.2 Semantik im Dokument beschrieben.
Nehmen wir an, wir haben eine Methode mit dem Namen displayLocalVariable, um die starke und schwache Referenz zu verstehen.
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
}
In der obigen Methode ist der Umfang der myName-Variablen auf die displayLocalVariable-Methode beschränkt. Sobald die Methode fertig ist, wird die Zuordnung der myName-Variablen, die die Zeichenfolge "ABC" enthält, aus dem Speicher aufgehoben.
Was nun, wenn wir den Wert der Variablen myName während des gesamten Lebenszyklus des View-Controllers beibehalten möchten? Dafür können wir die Eigenschaft namens username erstellen, die einen starken Bezug zur Variablen myName hat (siehe self.username = myName;
unter Code), wie unten,
@interface LoginViewController ()
@property(nonatomic,strong) NSString* username;
@property(nonatomic,weak) NSString* dummyName;
- (void)displayLocalVariable;
@end
@implementation LoginViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(void)viewWillAppear:(BOOL)animated
{
[self displayLocalVariable];
}
- (void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.username = myName;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
@end
Im obigen Code können Sie sehen, dass myName self.username zugewiesen wurde und self.username einen starken Verweis (wie wir in der Schnittstelle mit @property deklariert haben) auf myName hat (indirekt einen starken Verweis auf "ABC" -String). Daher wird String myName erst freigegeben, wenn self.username aktiv ist.
Weisen Sie nun DummyName myName zu. Dies ist eine schwache Referenz. Self.dummyName = myName; Im Gegensatz zu "Starke Referenz" wird "Mein Name" von "Schwach" nur so lange gespeichert, bis eine starke Referenz auf "Mein Name" vorhanden ist. Siehe untenstehenden Code, um die schwache Referenz zu verstehen.
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.dummyName = myName;
}
In dem obigen Code gibt es einen schwachen Verweis auf meinen Namen (d. H. Self.dummyName hat einen schwachen Verweis auf meinen Namen), aber es gibt keinen starken Verweis auf meinen Namen, daher kann self.dummyName den myName-Wert nicht halten.
Betrachten Sie nun noch einmal den folgenden Code:
-(void)displayLocalVariable
{
NSString myName = @"ABC";
NSLog(@"My name is = %@", myName);
self.username = myName;
self.dummyName = myName;
}
Im obigen Code hat self.username einen starken Verweis auf myName, daher hat self.dummyName jetzt auch nach Beendigung der Methode den Wert myName, da myName einen starken Verweis zugeordnet hat.
Wenn wir nun einen starken Verweis auf eine Variable erstellen, wird die Anzahl der Aufbewahrungen um eins erhöht und die nicht freigegebene Anzahl der Aufbewahrungen erreicht 0.
Hoffe das hilft.
Beispiel: @property (strong, nonatomic) ViewController * viewController;
@synthesize viewController;
Standardmäßig automatisch abrufen und auf Null setzen
Beispiel: @property (schwach, nichtatomar) IBOutlet UIButton * myButton;
@synthesize myButton;
Die Unterschiede zwischen stark und erhalten:
Die Unterschiede zwischen schwach und zuweisen: