wake-up-neo.net

Wann sollte ich Objekte in - (void) viewDidUnload anstatt in -dealloc freigeben?

Wofür ist die Funktion -(void)viewDidUnload gut?

Könnte ich nicht einfach alles in -dealloc? Wenn die Ansicht entladen würde, würde -dealloc trotzdem angerufen werden?

103
Thanks

Zusätzlich zu dem, was bereits angedeutet wurde, wollte ich mehr über die Logik hinter -viewDidUnload Herausfinden.

Einer der wichtigsten Gründe für die Implementierung ist, dass UIViewController - Unterklassen häufig auch Verweise auf verschiedene Unteransichten in der Ansichtshierarchie enthalten. Diese Eigenschaften könnten beispielsweise beim Laden von einer Schreibfeder oder programmgesteuert in -loadView Über IBOutlets festgelegt worden sein.

Die zusätzliche Inhaberschaft von Unteransichten durch UIViewController bedeutet, dass selbst wenn die Ansicht aus der Ansichtshierarchie entfernt und aus Speicherspargründen freigegeben wird, wodurch die Unteransichten auch von der Ansicht freigegeben werden, die Zuordnung nicht aufgehoben wird, da die UIViewController selbst enthält immer noch seine eigenen ausstehenden Aufbewahrungsverweise auf diese Objekte. Wenn Sie das zusätzliche Eigentumsrecht UIViewController für diese Objekte freigeben, wird sichergestellt, dass auch die Zuordnung aufgehoben wird, um Speicher freizugeben.

Die Objekte, die Sie hier freigeben, werden in der Regel neu erstellt und festgelegt, wenn die Ansicht UIViewControllerre-loaded Ist, entweder von einer Schreibfeder oder durch eine Implementierung von -loadView.

Beachten Sie außerdem, dass die Eigenschaft UIViewControllerview zum Zeitpunkt des Aufrufs dieser Methode nil ist.

51
Sean Murphy

Wie die Dokumentation sagt :

Es wird unter Bedingungen mit wenig Arbeitsspeicher aufgerufen, wenn der Ansichtscontroller seine Ansicht und alle mit dieser Ansicht verknüpften Objekte freigeben muss, um Arbeitsspeicher freizugeben.

In der gleichen Situation wird dealloc nicht aufgerufen. Diese Methode ist nur in OS3 und höher verfügbar. Mit der gleichen Situation in iPhone OS 2.x umzugehen, war ein echtes Problem!

Update Juli 2015 : Es sollte beachtet werden, dass viewDidUnload in iOS 6 veraltet ist, weil "Ansichten unter Bedingungen mit geringem Arbeitsspeicher nicht mehr gelöscht werden und so wird diese Methode nie aufgerufen. " Der moderne Rat ist also, sich keine Sorgen zu machen und dealloc zu verwenden.

21

Dies liegt daran, dass Sie in der Regel @property Als "(nonatomic, retain)" festlegen und der für Sie erstellte Setter das aktuelle Objekt freigibt und dann das Argument beibehält, d. H.

self.property = nil;

... tut etwas in der Art von:

[property release];
property = [nil retain];

Daher schlagen Sie zwei Fliegen mit einer Klappe: Speicherverwaltung (Freigabe des vorhandenen Objekts) und Zuweisen des Zeigers zu Null (da das Senden einer Nachricht an einen Nullzeiger Null zurückgibt).

Ich hoffe, das hilft.

9
gazzaaa87

Denken Sie daran, dass viewDidUnload eine Methode im Ansichtscontroller und nicht in der Ansicht ist. Die view'sdealloc -Methode wird aufgerufen, wenn die Ansicht entladen wird, aber die view controller'sdealloc -Methode wird möglicherweise erst später aufgerufen.

Wenn Sie eine Warnung zu wenig Arbeitsspeicher erhalten und Ihre Ansicht nicht angezeigt wird, was beispielsweise vorkommt, wenn Sie einen UIImagePickerController verwenden, um den Benutzer ein Bild aufnehmen zu lassen, wird Ihre Ansicht entladen und muss anschließend neu geladen werden.

8
David Maymudes

Apple veraltet viewWillUnload, jetzt sollten Sie didReceiveMemoryWarning oder dealloc verwenden, um Ihre Objekte freizugeben.

In iOS 6 sind die Methoden viewWillUnload und viewDidUnload von UIViewController jetzt veraltet. Wenn Sie diese Methoden zum Freigeben von Daten verwenden, verwenden Sie stattdessen die didReceiveMemoryWarning-Methode. Mit dieser Methode können Sie auch Verweise auf die Ansicht des View Controllers freigeben, wenn diese nicht verwendet wird. Zuvor müssten Sie testen, ob sich die Ansicht nicht in einem Fenster befindet.

Fazit:

Ansichtscontroller haben eine Ansichtseigenschaft. Normalerweise fügt eine Schreibfeder oder ein Teil des Codes dieser Ansicht andere Ansichten hinzu. Dies passiert häufig in einer -viewDidLoad-Methode wie folgt:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self createManyViewsAndAddThemToSelfDotView];
}

darüber hinaus kann eine NIB-Datei eine Schaltfläche erstellen und an die Ansicht des View Controllers anhängen.

Unter iPhone OS 2.2 mussten Sie beim Aufrufen von -didReceiveMemoryWarning vom System aus etwas freigeben, um Speicherplatz freizugeben. Sie können die Ansicht des gesamten View Controllers freigeben, wenn dies sinnvoll ist. Oder nur große speicherintensive Inhalte.

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
    // Release anything that's not essential, such as cached data
}

Jetzt gibt es in dem neuen OS 3.0 eine -viewDidUnload-Methode, die vom System aufgerufen wird, wenn die Ansicht wegen zu wenig Arbeitsspeicher entladen wurde (bitte korrigieren Sie mich: Wann genau wird dies aufgerufen?)

-viewDidUnload wird verwendet, um alle Objekte freizugeben, deren Eigentümer sowohl der Ansichtscontroller selbst als auch die Ansicht sind. Der Grund: Wenn ein Ansichtscontroller Verweise auf untergeordnete Ansichten der Ansicht, dh eine Schaltfläche, enthält, werden die untergeordneten Ansichten, auf die verwiesen wird, nicht freigegeben, da ihre Anzahl beibehalten> = 1 ist. Nachdem sie in -viewDidUnload freigegeben wurden, können sie freigegeben werden aus dem Gedächtnis.

6
Thanks

Wenn der Ansichts-Controller vom Navigations-Controller-Stapel abgerufen wird und an keiner anderen Stelle beibehalten wird, wird die Zuordnung aufgehoben und die Zuordnung wird anstelle von viewDidUnload aufgerufen. Sie sollten die in loadView erstellten Ansichten in dealloc freigeben, es ist jedoch nicht erforderlich, die Variablen auf nil zu setzen, da die Variablen kurz nach dem Aufruf von dealloc nicht mehr vorhanden sind.

5
Colin

Sie können alle Unteransichten freigeben, an denen Sie festhalten, z. B. die UIImageView, die Sie in Ihrer loadView-Methode beibehalten haben, oder besser das Bild, das sich in dieser UIImageView befand.

3
drvdijk