1

Ich habe eine Instanz eines UITableView und eine separate Klasse, die den Delegate- und Datenquellenprotokollen folgt. Ich tue dies, wie so:Autorelease und "zuweisen" Eigenschaften in Objective-C? (Auf dem iPhone)

SubjectTableViewHandler *handler = [[[SubjectTableViewHandler alloc] init] retain]; 
tv.delegate = handler; 
tv.dataSource = handler; 
[handler autorelease]; 

Ich will nicht den Handler als Ivar halten, und wenn ich die retain Anruf am Ende nehmen ab, wenn die autorelease geschieht, wird es gesendet release, dann zum Pool hinzugefügt, was eine EXC_BAD_ACCESS verursacht. So aktuell, behalten die Zählung:

(1) At init: 1 
(2) At retain: 2 
(3) delegate/datasource properties are 'assign', still 2 
(4) At autorelease: 1, now in autorelease pool. 

Aber dann, da die Eigenschaften ‚assign‘, werden sie nie gelöst werden, die Beibehaltungszähler wird nie 0 getroffen, und die Prozedur wird sowieso nie freigegeben werden. Gibt es einen effizienteren Weg, dies zu erreichen, als den Handler als einen Ivar zu halten und ihn in der dealloc Methode freizugeben?

Antwort

5

Wenn Sie das Objekt mithilfe von init initialisieren, beanspruchen Sie es als Eigentümer, und es gibt keinen Grund, es zurückzurufen. Sie möchten auch keine Autorelease aufrufen, da dies dazu führt, dass das Objekt in der Run-Schleife freigegeben wird.

Da Sie den Handler behalten müssen (damit Ihr tableView die delegate/dataSource -Methoden aufrufen kann) und einen Verweis auf den Handler, nachdem die Methode zurückgegeben wurde (damit Sie sie freigeben können, wenn Sie die tableView anzeigen), Am saubersten wäre es, es zu einem Ivar zu machen.

+0

Stimme hier zu. Kämpfe nicht gegen den Rahmen. Gibt es einen bestimmten Grund, warum Sie keinen Ivar verwenden möchten? – amattn

+0

Es war nicht sinnvoll, einen ivar zu haben, da die Variable außerhalb der Methode, die den Handler setzt, keine Verwendung hat. Die perfekte Lösung wäre, wenn die Eigenschaften der Datenquelle/des Delegaten beibehalten würden. Dann könnten sie gesetzt und freigegeben werden, und die Klasse, die sie setzt, würde sich darüber keine Sorgen mehr machen müssen. –

+0

Ich denke, der Grund für die Zuweisung ist, dass Sie keinen Aufbewahrungszyklus erstellen. Sie erstellen häufig das Objekt, das einen Delegaten von dem Objekt übernimmt, das zum Delegaten wird. In diesem Fall möchten Sie nicht, dass das Objekt seinen Delegaten beibehält und sein Delegat das Objekt behält. –

1

Die einzige Lösung, die ich sehen kann, ist, wie Sie bereits erwähnt haben, es zu einem ivar zu machen und es parallel zur Tabelle zu speichern, zuzuweisen und freizugeben.

+0

Ich frage mich, warum dies auf -2 downvoted ist? Einen Verweis auf die Datenquelle in einer Instanzvariablen irgendwo zu speichern * ist * das Richtige. –

+0

Ich kann nicht widersprechen, aber Mark hat Recht. Ich habe vielleicht ursprünglich falsch gelesen, aber nur für das Protokoll, ich habe fälschlicherweise diese Antwort abgelehnt. (Entschuldigung) – amattn

0

Es hängt alles von Ihrer Verwendung der Tabellenansicht ab.

Üblicherweise erstellen Sie einen View-Controller, bei dem es sich um einen Delegaten für die Tabelle und die Tabelle für den Controller handeln kann.

Als weitere Alternative können Sie von UITableView erben und es sich selbst delegieren.

Manchmal ist es besser, einen Singleton-Delegaten zu verwenden.

Darüber hinaus ist das erste Argument in Tabellendelegatenmethoden tableview, sodass ein Delegatobjekt mehrere Tabellen verarbeiten kann.