Frage

Hier ist eine gängige Praxis sehe ich oft (auch von einem sehr beliebten iPhone-Entwicklerbuch)

In der H-Datei:

@interface SomeViewController : UIViewController
{
  UIImageView *imgView;
}

Irgendwo in der .m-Datei:

imgView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen]
applicationFrame]];
[imgView setImage:[UIImage imageNamed:@"someimage.png"]];
[self addSubview:imgView];
[imgView release];

Und später, sehen wir diese ...

- (void) dealloc
{
  [imgView release];
  [super dealloc];

} 

Da imgView eine passende alloc hat und loslassen, ist die Freisetzung von imgView in dealloc notwendig?

Wo ist der imgView durch den addSubview Anruf erhalten entfielen?

War es hilfreich?

Lösung

Ja, das Code hat Probleme. Es gibt den imgView zu früh, die möglicherweise Abstürze in seltenen Fällen dazu führen können, speichert ein Objekt in einer Instanzvariablen, ohne es zu halten, und es ist nur allgemein über die Speicherverwaltung geht in die falsche Richtung.

Ein richtiger Weg, dies zu tun sei:

@interface SomeViewController : UIViewController
{
    UIImageView *imgView;
}
@property (nonatomic, retain) UIImageView *imgView;

Und bei der Umsetzung;

@synthesize imgView;

Irgendwo in dem Modul ein:

//Create a new image view object and store it in a local variable (retain count 1)
UIImageView *newImgView = [[UIImageView alloc] initWithFrame:self.view.bounds];
newImgView.image = [UIImage imageNamed:@"someimage.png"];

//Use our property to store our new image view as an instance variable,
//if an old value of imgView exists, it will be released by generated method,
//and our newImgView gets retained (retain count 2)
self.imgView = newImgView;

//Release local variable, since the new UIImageView is safely stored in the
//imgView instance variable. (retain count 1)
[newImgView release];

//Add the new imgView to main view, it's retain count will be incremented,
//and the UIImageView will remain in memory until it is released by both the
//main view and this controller. (retain count 2)
[self.view addSubview:self.imgView];

Und die dealloc bleibt das gleiche:

- (void) dealloc
{
    [imgView release];
    [super dealloc];
}

Andere Tipps

Der Code ist nicht korrekt. Sie werden am Loslassen imgView beenden, nachdem es freigegeben worden ist.

In .m-Datei, Sie:

  1. alloc es -> Sie besitzen es
  2. fügen Sie es als ein Subview -> Sie und die UIView besitzt es
  3. release es -> Sie besitzen es nicht

Dann in dealloc, release Sie imgView obwohl, wie wir in Schritt 3 oben hergestellt, Sie es nicht besitzen. Wenn Sie [super dealloc] call, wird die Ansicht all seiner Subviews release, und ich denke, Sie werden eine Ausnahme erhalten.

Wenn Sie eine Ivar von imgView behalten wollen, schlage ich vor, nicht Aufruf release, nachdem Sie es als ein Subview hinzufügen, und halten Sie Ihre dealloc gleich. Auf diese Weise, auch wenn imgView irgendwann aus der Sicht Hierarchie entfernt ist, werden Sie noch einen gültigen Verweis darauf haben.

Der Code ist falsch, sollten Sie es nicht in der init-Methode veröffentlichen, nur wenn dealloc genannt wird (das ist, wenn Sie es als Ivar behalten möchten, brauchen Sie nicht zu, wenn Sie einen Zeiger auf sie brauchen anderswo seit addSubview. wird die Ansicht für Sie behalten)

Ich glaube, der Grund, warum es eigentlich nicht abstürzt, weil es immer noch wird von der übergeordneten Klasse gehalten wird (aus dem Aufruf von addSubview :), so dass, wenn es in dealloc freigegeben ist, die aus tatsächlich ausgeglichen sind. Die Ansicht entfernt wahrscheinlich selbst aus dem Superview, wenn es unmittelbar danach freigegeben ist, so dass, wenn [super dealloc] genannt wird, ist es nicht über freigegeben wird. Das ist meine Vermutung, bei Leasing.

Veröffentlichung in init ist falsch.

Sie haben erwähnt, „gängige Praxis“ und ein un-named Buch. Ich schlage vor, bei den kanonischen Beispielen von Apple suchen: ViewTransitions ein gutes Beispiel für diesen Fall ist (und 2 Ansichten zu booten;)

http://developer.apple.com/iphone/library /samplecode/ViewTransitions/index.html

(ich habe nicht genug Ruf Kommentar hinzufügen noch.)

@bentford: Korrigieren Sie mich, wenn ich falsch liege, aber ich glaube, dass, um die imgView Eigenschaft synthetisierte Setter verwenden Sie „self.imgView“ müssen:

self.imgView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen]

Wenn Sie nicht über selbst. , es ist nur die Ivar verwenden, und es ist nicht immer die zusätzliche beibehalten.

Die grundlegende Antwort ist, es sollte nur ein [imgView release] im Beispielcode sein (, ob es nach addSubview ist oder in dealloc ). Allerdings würde ich [imgView release] von dealloc entfernen und lassen Sie ihn nach addSubview.

Es gibt einen Haken auf dem iPhone; mit didReceiveMemoryWarning, können Sie Objekte (, die eine gesamte Ansicht ) haben unter Ihnen freigegeben werden. Wenn Sie eine Anwendung weit behalten Satz haben und Sie nicht respektieren Speicher dann könnte man die Anwendung finden einfach getötet werden.

Ein gutes Beispiel ist:
wenn Sie der Meinung eines verschachtelten Satz von 3 Ansichten, Ansicht 1-> Ansicht 2-> View 3. die ‚viewDidLoad‘ und ‚viewDidUnload‘ Anrufe Als nächstes betrachten. Wenn der Benutzer zur Zeit in ‚View 3‘ ist, dann ist es möglich, dass Ansicht1 entladen wird, und das ist, wo es böse wird.
 Wenn Sie ein Objekt innerhalb viewDidLoad zugeordnet und entließen sie nicht, nachdem er dem Subview hinzufügen, dann das Objekt wird nicht freigegeben, wenn view1 entladen wird, aber wird view1 noch entladen.
 viewDidLoad läuft wieder und Ihr Code läuft wieder, aber jetzt haben Sie zwei Instanzen des Objekts statt einer; Ein Objekt wird mit der vorher abgeladen Ansicht in Niemandsland sein und das neue Objekt wird für die aktuelle Ansicht sein. Spülen, schäumen, und wiederholen Sie und finden Sie Ihre Applikation von Speicherlecks abstürzt.

In diesem Beispiel, wenn der angegebene Code-Block flüchtig ist und eine Chance hat, wieder ausgeführt werden (, ob wegen Speicher oder einer ungeladenen Ansicht ), würde ich [imgView release]; von dealloc entfernen und hinterlassen nach addSubView.

Hier ist ein Link zu den grundlegenden behalten / Release-Konzepte: http://www.otierney.net/objective-c.html#retain

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top