web-dev-qa-db-de.com

Objective-C ARC: Stark gegen Beibehalten und Schwach gegen Zuweisen

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?

361
Jakub Arnold

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.

228
JeremyP

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:

  1. atomic // default
  2. nichtatomar
  3. stark = // Standard beibehalten
  4. schwach
  5. behalten
  6. // default zuweisen
  7. unsafe_unretained
  8. kopieren
  9. schreibgeschützt
  10. readwrite // default

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 !!

Variable Eigenschaftsattribute oder Modifikatoren in iOS

1. stark (iOS4 = behalten)

  • es heißt "behalte das auf dem Haufen, bis ich nicht mehr darauf zeige"
  • mit anderen Worten: "Ich bin der Besitzer, Sie können dies nicht aufheben, bevor Sie mit dem gleichen Ziel wie Beibehalten zufrieden sind."
  • Sie verwenden strong nur, wenn Sie das Objekt behalten müssen.
  • Standardmäßig sind alle Instanzvariablen und lokalen Variablen starke Zeiger.
  • Wir verwenden generell strong für UIViewControllers (übergeordnete Elemente der Benutzeroberfläche).
  • strong wird mit ARC verwendet und hilft Ihnen im Grunde, da Sie sich keine Gedanken über die Anzahl der Aufbewahrungen eines Objekts machen müssen. ARC gibt es automatisch für Sie frei, wenn Sie damit fertig sind. Wenn Sie das Schlüsselwort strong verwenden, bedeutet dies, dass Sie Eigentümer des Objekts sind.

Beispiel:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;

2. schwach -

  • es heißt "behalte das so lange, wie jemand anderes stark darauf hinweist"
  • das gleiche wie zuweisen, kein behalten oder freigeben
  • Eine "schwache" Referenz ist eine Referenz, die Sie nicht beibehalten.
  • Für IBOutlets (Childs von UIViewController) wird im Allgemeinen "weak" verwendet. Dies funktioniert, da das untergeordnete Objekt nur so lange vorhanden sein muss, wie das übergeordnete Objekt vorhanden ist.
  • ein schwacher Verweis ist ein Verweis, der das referenzierte Objekt nicht vor der Erfassung durch einen Garbage Collector schützt.
  • Schwach ist im Wesentlichen eine nicht zurückgehaltene Eigenschaft zuzuweisen. Außer wenn das Objekt freigegeben wird, wird der schwache Zeiger automatisch auf Null gesetzt

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

  • es wird beibehalten, der alte Wert wird freigegeben und es wird beibehalten zugewiesen. Gibt an, dass der neue Wert gesendet werden soll
  • bei Zuordnung behalten und den alten Wert absenden - freigeben
  • behalten ist das gleiche wie stark.
  • Apple sagt, wenn Sie beibehalten schreiben, wird es automatisch konvertiert/funktioniert nur wie stark.
  • methoden wie "alloc" beinhalten ein implizites "retain"

Beispiel:

@property (nonatomic, retain) NSString *name;

@synthesize name;

4.zuweisen

  • assign ist die Standardeinstellung und führt einfach eine variable Zuordnung durch
  • assign ist ein Eigenschaftsattribut, das dem Compiler mitteilt, wie die Setter-Implementierung der Eigenschaft synthetisiert wird
  • Ich würde Assign für primitive C-Eigenschaften und Schwach für schwache Verweise auf Objective-C-Objekte verwenden.

Beispiel:

@property (nonatomic, assign) NSString *address;

@synthesize address;
600
swiftBoy

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.

39
Tricertops

nichtatomar/atomar

  • nichtatomar ist viel schneller als atomar
  • verwenden Sie immer nonatomic, es sei denn, Sie haben eine sehr spezielle Anforderung an atomic, die selten sein sollte (atomic garantiert keine Threadsicherheit - blockiert den Zugriff auf die Eigenschaft nur, wenn sie gleichzeitig von einem anderen Thread festgelegt wird).

stark/schwach/zuweisen

  • verwenden Sie strong , um Objekte beizubehalten. Obwohl das Schlüsselwort retain synonym ist, empfiehlt es sich, stattdessen strong zu verwenden
  • verwenden Sie schwach , wenn Sie nur einen Zeiger auf das Objekt haben möchten, ohne es beizubehalten. Dies ist nützlich, um Beibehaltungszyklen (dh Delegaten) zu vermeiden Zeiger, wenn das Objekt freigegeben wird
  • benutze weise für Primative zu - genau wie schwach, außer dass es das Objekt beim Loslassen nicht vernichtet (standardmäßig gesetzt)

(Optional)

Kopie

  • verwenden Sie diese Option, um eine flache Kopie des Objekts zu erstellen
  • es empfiehlt sich, unveränderliche Eigenschaften immer auf Kopieren zu setzen. Da veränderbare Versionen in unveränderliche Eigenschaften übergeben werden können, wird durch Kopieren sichergestellt, dass Sie immer mit einem unveränderlichen Objekt arbeiten
  • wenn ein unveränderliches Objekt übergeben wird, wird es beibehalten. Wenn ein veränderliches Objekt übergeben wird, wird es kopiert

schreibgeschützt

  • verwenden Sie diese Option, um die Einstellung der Eigenschaft zu deaktivieren. (Verhindert, dass Code kompiliert wird, wenn ein Verstoß vorliegt.)
  • sie können die vom Getter gelieferten Daten ändern, indem Sie die Variable entweder direkt über ihre Instanzvariable oder innerhalb der Getter-Methode selbst ändern
38
Vadoff

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.

20
Mingming

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.

  • Schwacher Bezug

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.

4
Mahadev Mandale

Stark:

  • Eigenschaft wird nicht zerstört, aber nur wenn Sie die Eigenschaft auf Null setzen, wird das Objekt zerstört
  • Standardmäßig sind alle Instanzvariablen und lokalen Variablen starke Zeiger.
  • Sie verwenden strong nur, wenn Sie das Objekt behalten müssen.
  • Wir verwenden generell strong für UIViewControllers (übergeordnete Elemente der Benutzeroberfläche).
  • IOS 4 (nicht ARC) Wir können Retain KeyWord verwenden
  • IOS 5(ARC) Wir können ein starkes Schlüsselwort verwenden

Beispiel: @property (strong, nonatomic) ViewController * viewController;

@synthesize viewController;

Schwach

Standardmäßig automatisch abrufen und auf Null setzen

  • Wir verwenden generell schwach für IBOutlets (UIViewController's Childs) und delegieren
  • das gleiche wie zuweisen, kein behalten oder freigeben

Beispiel: @property (schwach, nichtatomar) IBOutlet UIButton * myButton;

@synthesize myButton;

2
Nikunj Patel

Die Unterschiede zwischen stark und erhalten:

  • In iOS4 ist stark gleich zu behalten
  • Dies bedeutet, dass Sie das Objekt besitzen und es auf dem Haufen behalten, bis Sie nicht mehr darauf zeigen
  • Wenn Sie "behalten" schreiben, funktioniert dies automatisch genauso wie "stark"

Die Unterschiede zwischen schwach und zuweisen:

  • Ein "schwacher" Verweis ist ein Verweis, den Sie nicht behalten und den Sie behalten, solange ein anderer stark darauf hinweist
  • Wenn das Objekt freigegeben wird, wird der schwache Zeiger automatisch auf Null gesetzt
  • Ein "assign" -Eigenschaftsattribut teilt dem Compiler mit, wie die Setter-Implementierung der Eigenschaft zu synthetisieren ist
1
Chen Rui