16

Ich bin neu in Objective-C und ich versuche Speicherverwaltung zu verstehen, um es richtig zu machen.Wann wird ein automatisch freigegebenes Objekt tatsächlich freigegeben?

Nach den hervorragenden
Memory Management Programming Guide for Cocoa von Apfel meiner einzige Sorge zu lesen ist, wenn tatsächlich ein Autoreleased Objekt in einer iPhone/iPod Applikation freigegeben wird. Mein Verständnis ist am Ende einer Laufschleife. Aber was definiert eine Laufschleife in der Anwendung?

Also habe ich mich gefragt, ob das folgende Stück Code richtig ist. Angenommen, ein Objekt

@implementation Test 

- (NSString *) functionA { 
    NSString *stringA; 
    stringA = [[[NSString alloc] initWithString:@"Hello"] autorelease] 
    return stringA; 
} 

- (NSString *) functionB { 
    NSString *stringB; 
    stringB = [self functionA]; 
    return stringB; 
} 

- (NSString *) functionC { 
    NSString *stringC; 
    stringC = [self functionB]; 
    return stringC; 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    NSString* p = [self functionC]; 
    NSLog(@"string is %@",p); 
} 

@end 

Ist dieser Code gültig?

Aus dem Text Apfel ich, dass der NSString von Funktioneine im Rahmen FunktionD gültig ist zurückgekehrt zu verstehen. Ich bin mir nicht sicher, ob es in functionC und in ViewDidLoad gültig ist.

Danke!

Antwort

17

Ja, Ihre Funktionen sind gültig und geben Objekte unter Verwendung der korrekten Cocoa-Konventionen für Retain/Release/AutoRelease/Copy zurück.

Um Ihre Frage zu beantworten, was der Runloop ist, ruft er in der main() -Funktion Ihrer Anwendung UIApplicationMain() auf. Sie können sich vorstellen UIApplicationMain etwas wie folgt aussieht:

void int UIApplicationMain (int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName) { 
    UIApplication *app = /* create app using principalClassName */; 
    [app setDelegate:/* create delegate using delegateClassName */]; 
    while (![app shouldTerminate]) { 
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
     event = [app getNextEvent]; 
     [app dispatchEvent:event]; 
     [pool drain]; 
    } 
} 

Das While-Schleifen ist ähnlich zu dem, was die UIKit tatsächlich tun wird, und jede Reise durch diese while-Schleife ist wie eine Reise durch die Runloop, wo die Funktion GetNextEvent Blöcke warten damit ein Ereignis eintritt. Alle Ihre Methoden werden typischerweise von etwas wie dispatchEvent: aufgerufen. Sie könnten versuchen, einen Unterbrechungspunkt in einer Ihrer Methoden zu setzen, wie eine IBAction, und oben im Debugger-Aufruf-Stack nach oben zu schauen, um die Namen der UIKit-Methoden zu sehen, die die Ereignisse und Runloops verarbeiten. Da jede Ihrer Methoden innerhalb dieser while-Schleife aufgerufen wird, wird jedes Mal, wenn Sie Autorelease für ein Objekt aufrufen, dieses Objekt zu diesem externen Pool in der Ausführungsschleife hinzugefügt. Wenn das aktuelle Ereignis beendet ist, wird der Pool entleert, und diese Objekte werden schließlich Freigabemeldungen gesendet.

Eine letzte Anmerkung. Es kann mehrere Autorelease-Pools geben, die nicht immer am Ende der Ereignisschleife liegen. Manchmal können Sie Zehntausende von Objekten auf einer Reise durch die Ereignisschleife zuordnen. In diesem Fall können Sie weitere interne Pools für die automatische Freigabe in Ihren eigenen Methoden einrichten, um die Anzahl der automatisch freigegebenen Objekte in den Pools für die automatische Freigabe beizubehalten. Automatische Freigabepools können gestapelt werden.

+0

Verstehe ich richtig, dass, wenn ich keine Autorelease-Pools erstellt habe, alle automatisch freigegebenen Variablen im Speicher verbleiben, bis die Anwendung nicht geschlossen wird? – Burjua

+0

Art von, erstellen die System-Frameworks einige Autorelease-Pools für Sie an der Spitze des Stapels des Haupt-Thread in Methoden wie UIApplicationMain(). Wenn Sie jedoch einen eigenen Thread gestartet haben und keinen Pool erstellt haben, dann würden diese Objekte tatsächlich undicht sein. Die Autorelease-Methode meldet sich in diesem Fall an der Konsole an. –

+0

Ok, danke, aber das ist seltsam, es ist normal, Konstruktoren zu verwenden, die automatisch freigegebene Objekte zurückgeben und sie nicht freigeben, aber es ist eigentlich dasselbe, Speicherleck zu haben (Speicher wird zugewiesen, bis Anwendung geschlossen wird). Oder ich verstehe etwas nicht? – Burjua

0

Mit diesem Code ist nichts falsch. Es wird kompiliert und ausgeführt, wie Sie es erwarten.

Das NSString Objekt aus functionA zurückgekehrt ist bei der Rückkehr immer noch gültig, da sie den Stapel an den nächsten Mann weitergegeben Sein (functionB), der nun den Überblick über sie hält.

+3

"Passed down the Stack" ist wahrscheinlich nicht die beste Wahl der Phrase, weil es bedeutet, dass ein Stack für Rückgabewerte verwendet wird, was nicht immer der Fall ist. –

Verwandte Themen