2010-12-31 11 views
15

Ich habe eine UITableViewController. Ich erstelle eine benutzerdefinierte headerView für sie tableView im loadView Methode ist wie so:Custom UITableView headerView verschwindet nach Speicher Warnung

(void)loadView { 
    [super loadView]; 

    UIView* containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height * 2)]; 
    containerView.tag = 'cont'; 
    containerView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; 

    UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom]; 
    button.frame = CGRectMake(padding, height, width, height); 
    ... //configure UIButton and events 

    UIImageView* imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"image.png"] highlightedImage:[UIImage imageNamed:@"highlight.png"]];  
    imageView.frame = CGRectMake(0, 0, width, height); 
    ... //configure UIImageView 

    [containerView addSubview:button]; 
    [containerView addSubview:imageView]; 
    self.tableView.tableHeaderView = containerView; 

    [imageView release]; 
    [containerView release]; 
} 

Keiner der anderen Methoden (viewDidLoad/Unload, usw.) sind überlastet.

Dieser Controller befindet sich in einer Registerkarte. Wenn ich zu einer anderen Registerkarte wechsle und eine Speicherwarnung simuliere und dann zu dieser Registerkarte zurückkehre, fehlt in meiner UITableView mein custon header. Alle Zeilen/Abschnitte sind sichtbar, wie ich es erwarten würde. Wenn ich einen BP in den Code loadView einfüge, sehe ich, dass er aufgerufen wird, wenn ich nach der Speicherwarnung zu der Registerkarte zurückwechsle, und trotzdem kann ich die Kopfzeile nicht sehen.

Irgendwelche Ideen über das, was mir hier fehlt?

EDIT: Dies geschieht auf dem Gerät und dem Simulator. Auf dem Gerät lasse ich einfach eine Speicherwarnung durch Öffnen einer Reihe verschiedener Apps, während sich meine im Hintergrund befindet.

+0

Ich denke, Sie Code in Ihren ViewDidUnload() -Methode wie dieses: self.tableView.tableHeaderView = nil; ? –

+0

Nein. "Keine der anderen Methoden (viewDidLoad/Unload, usw.) sind überlastet." Brauche ich es? Warum? – psychotik

+0

Verwirrt. Hoffe, jemand anderes kann helfen. –

Antwort

2

Halten Sie containView, anstatt es zu veröffentlichen. Und geben Sie es in tableView: viewForHeaderInSection: (UITableViewDelegate-Methode) zurück.

+0

Was ist los mit der Freigabe? 'tableHeaderView' behält es bei. Unabhängig davon wird 'loadView' aufgerufen, wenn ich zu dieser Registerkarte zurückkehre, so dass ich nicht verstehe, warum es anfänglich funktioniert, aber nicht nach einer Mem-Warnung. – psychotik

-2

Das einzige Problem, das ich sehen kann, indem Sie nur Ihre loadView betrachten, ist, dass Sie versuchen, Ihre containerView mit einer Zeichenfolge zu markieren. Soweit ich weiß, sollte das ein NSInteger sein.

+0

Das ist keine Zeichenfolge. Beachten Sie die einfachen Anführungszeichen. – psychotik

+0

Es ist kein 'NSString', aber es ist ein char *, nein? Die Eigenschaft tag erwartet einen 'NSInteger'. – Bringo

+0

Nr. Char * wird immer noch mit doppelten Anführungszeichen deklariert. Das ist ein 32-Bit-int-Wert, definiert als sequentielle Zeichen. Ich versichere Ihnen, dass es gültig ist und nicht mit diesem Problem verbunden ist. – psychotik

-1

Dieses Problem ist bekannt. Wenn Sie beispielsweise TableViewDelegate tableView:viewForHeaderInSection: verwenden, wird es auch nicht funktionieren.

Das Problem ist iOS und nicht Sie. Es gibt nicht viele Fragen über die TableHeaderView, weil niemand sie verwendet, und so hat Apple keine BugTracker Einträge ...

Werfen Sie einen Blick auf eine ältere Frage: here. Und here sind andere Probleme.

Also ich denke wirklich, es ist ein SDK Fehler ...

+0

Was^gesagt.Beachten Sie, dass dies wie erwartet funktioniert hat, bis eine Speicherwarnung angezeigt wird. Daher glaube ich nicht, dass irgendetwas grundsätzlich falsch daran ist, wie ich dem View Objekte erstelle/erweise. – psychotik

6

die Loadview-Methode nicht super nennen sollte. Versuchen Sie, [super loadView] zu entfernen. und das könnte dein Problem lösen. Die anderen überschriebenen View-Methoden (viewDidLoad, viewWillAppear etc.) können super gut aufrufen. Lesen Sie die Dokumentation unter:

http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html

zur Bestätigung.

+0

Es heißt explizit in loadView: "Ihre benutzerdefinierte Implementierung dieser Methode sollte nicht super aufrufen" – Eiko

+0

Das ist nicht das Problem, aber danke für die Notiz. – psychotik

+1

Interessanterweise gibt die UITableViewController-Klassenreferenz an: "Sie können loadView oder eine andere Superklassenmethode überschreiben, aber wenn Sie sicher sind, rufen Sie die Superklassenimplementierung der Methode auf, normalerweise als erster Methodenaufruf." – cduhn

-1

Ein reloadData in der Tabellenansicht könnte helfen

+0

Hey, danke für die -1 Stimmen, aber ich habe in der Vergangenheit meistens gesehen, dass korrekte Tabellenansichten ihre Header verlieren, nur um mit einem Table-Reload erledigt zu werden. –

0

Was sind Breite und Höhe? Ist es möglich, dass sie nach einer Speicherwarnung Null sind?

+0

Guter Gedanke - Ich habe überprüft, dass sie nach der Speicherwarnung gültig sind. – psychotik

0

das ist der normale Weg, iOS verwenden diese Möglichkeit, Speicher zu reduzieren, während Speicherproblem zu erhalten, dann wird es einige UI-Element freigeben, die auch Methode 'DidUnLoad' aufrufen ... Sie müssen die HeaderView in der Methode freigeben 'didUnLoad', auf Null gesetzt, und dann in der Methode 'didLoad', um die HeaderView zu erstellen, wenn es Null ist und dann auch TableView hinzufügen .... iOS wird automatisch einige UI-Elemente während Gesicht Speicher Warnung.

2

Ich hatte ein ähnliches Problem, obwohl es nicht die Situation des OP basierend auf seinem Code zu erklären scheint; Ich möchte es nur hierhin schreiben, falls irgendjemand anderes darauf stößt.

Ich behalte meine Header-Ansicht in einer Instanzvariable. In meinem ViewDidLoad überprüfe ich, ob diese Variable Null ist, wenn es dann ist, erstelle ich die Ansicht, behalte und setze die Instanzvariable darauf und setze tableHeaderView darauf. Das Problem ist, dass diese Bedingung nur einmal zutrifft, weil meine Instanzvariable niemals Null ist, nachdem ich sie das erste Mal erstellt habe. die tableHeaderView Eigenschaft tableHeaderView der Eigenschaft wird jedoch auf Null gesetzt, wenn es eine Speicherwarnung gibt, so dass es keine Header-Ansicht mehr geben wird, obwohl ich noch die Ansicht in einer Instanzvariable habe.

Die Lösung war, die Prüfung zu ändern, um zu sehen, ob die Eigenschaft der Tabellenansicht tableHeaderView ist Null (und dann die Header-Ansicht jedes Mal neu erstellen, die auf Null gesetzt wird), oder (da in diesem Fall ich noch Wenn die View in einer Instanzvariable beibehalten wird, verschiebt sich die Zuweisung zu tableHeaderView außerhalb des if-Blocks. Daher werden wir jedesmal, wenn viewDidLoad ausgeführt wird, die Headeransicht tableHeaderView zuweisen, falls sie auf null gesetzt wurde.

+0

+1 @psychotik In Bezug auf den Anwendungsfluss ist es besser, den 'headerView'-Code in' viewDidLoad' anstatt 'loadView' zu haben:' loadView' soll einfach tun, dass bei der Rückkehr 'self.view' gesetzt wird. Sobald "loadView" zurückkehrt, wird "viewDidLoad" für die Controller-Klasse aufgerufen, wo Sie weitere Eigenschaften festlegen können. Ich würde sagen, implementieren Sie die Einstellung der Header-Ansicht in 'viewDidLoad', und löschen Sie es in' viewDidUnload'. – darvids0n

0

Ich stieß gerade auf ein ähnliches Problem, das verursacht, dass mein benutzerdefinierter Header für das uitableview nach Erhalt einer Speicherwarnung nicht neu geladen wurde. meine aktuelle Implementierung der Header zu erstellen, ist

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    if (_tableHeaderView == nil) 
    { 
     [[NSBundle mainBundle] loadNibNamed:@"DetailHeaderView" owner:self options:nil]; 
     self.tableView.tableHeaderView = _tableHeaderView; 
    } 
} 

und das Problem, das ich einfach hinzugefügt, um diese Linie zu meinem didReceiveMemoryWarning

_tableHeaderView = nil 

und nun fix es neu lädt, nachdem ein Speicher Warnung gesendet wird.
Tut mir leid, wenn dies bereits beantwortet wurde, aber ich sah keine klare Antwort für mein Problem und dachte, ich würde dies hier für jemand anderen in meiner Situation veröffentlichen.

Glücklich Coding

Verwandte Themen