2009-03-24 12 views
4

Was ist die beste Methode zum Zurückhalten und Freigeben von Objekten, die an Klassenmethoden übergeben werden?Object-Retain-Verhalten von Objective-C-Klassenmethoden

Zum Beispiel, wenn Sie einen "Klassenvariable" haben erklärt, wie so:

static NSString *_myString = nil 

... das Richtige ist, dies zu tun:

+ (void)myClassMethod:(NSString *)param { 
    _myString = param; 
} 

..., die das hat Nachteil, dass der Aufrufer eine Zählung beibehalten muss, die nicht null ist, um eine vorzeitige Freigabe zu verhindern. Alternativ könnte man dies tun:

+ (void)myClassMethod:(NSString *)param { 
    [_myString autorelease]; 
    _myString = [param retain]; 
} 

... was den Nachteil hat, dass ohne eine entsprechende Klasse-Ebene dealloc nennen es ein Speicherleck wird. Oder sollte eine solche Klassenvariable Schikane vollständig vermieden werden, vielleicht mit einer Singleton-Klasse, die die Lebensdauer dieser Art von Objekten auf konventionellere Weise verwaltet?

Hier sind Apple's docs on creating a singleton instance.

Der Code, mit dem ich arbeite, ist das sehr glatte (aber immer noch neue) Objective Resource Projekt (http://www.iphoneonrails.com/).

+0

Sie stellen die falsche Frage. Anstatt nach globalen Variablen zu fragen, sollten Sie nach Hilfe fragen, um Ihre globalen Variablen loszuwerden. Und ja, auch wenn Sie dies hinter einer Klassenmethode (oder als Singleton) verbergen, ist dies immer noch eine globale Variable. – Sven

Antwort

3

Bewahren und lösen, absolut. Es ist kein Leck, denn der einzige Zeitpunkt, an dem eine Klasse dealloc aufgerufen wird, ist, wenn das Programm endet - zu diesem Zeitpunkt wird der Speicher trotzdem freigegeben. Dies zu tun wäre mühsamer und widerspricht den Cocoa-Richtlinien zur Speicherverwaltung.

Ob es eine Klassenmethode oder ein Singleton sein sollte: Klassen selbst sollten in der Regel nicht viel unabhängige Funktionalität haben. Sie wurden in Objective-C nicht so entworfen, wie Sie an den fehlenden Klassenvariablen sehen können. Klassenmethoden sollten sich im Allgemeinen mit der Erstellung und Verwaltung von Instanzen und manchmal mit dem Speichern gemeinsamer Eigenschaften oder Standardwerte für alle Instanzen befassen. Die eigentliche Funktionalität einer Klasse sollte in Instanzen gehen. Das ist die Konvention in Objective-C.

(Natürlich gibt es keinen Objective-C Gott und du bist frei Konventionen zu ignorieren, aber das ist die allgemeine Weisheit.)

+0

Klassen haben keine Dealloc-Methode, nur Instanzen. – dreamlax

+0

Ja, es gibt keine Dealloc für eine Klasse - aber es spielt keine Rolle.Speicher, der rechtmäßig von einem globalen Programmende gehalten wird, wird normalerweise nicht als Leck betrachtet (alle Singletons funktionieren so). Verwenden Sie definitiv einen behalten. –

+0

Ich weiß, dass Klassen keine Dealloc-Methoden haben. Das meinte ich: Selbst wenn Klassen solche Methoden hätten, würden sie nie aufgerufen werden. – Chuck

3

Auch im Fall von NSString oder jeder Klasse, die wandelbar Varianten hat (wie NSArray oder NSDictionary), würde ich dringend empfehlen, den Parameter zu kopieren, anstatt ihn zu behalten. Wenn die Zeichenfolge, die der Anrufer Ihnen übergeben hat, eine NSMutableString war, könnte sich der Wert später ändern und auch in Ihrer Klasse. Dies ist wahrscheinlich nicht das, was Sie wollen, so würde ich dies tun raten:

+ (void)myClassMethod:(NSString *)param { 
    [_myString release]; 
    _myString = [param copy]; 
} 

Die copy Methode eine Kopie macht und setzt die Zählung auf 1 halten, so dass Sie alle so weit wie Beibehaltung der Variable gesetzt ist besorgt. Und als zusätzlichen Bonus, wenn der Aufrufer Ihnen eine NSString gibt, ist diese Klasse schlau genug zu wissen, dass ihr Wert sich nicht ändern kann, also behält sie sich einfach, um eine Kopie des Objekts zu vermeiden. Wie schlau ist das?