Meine App hat zwei Status: angemeldet und nicht angemeldet, und ich habe die folgende Architektur (stark vereinfacht):
- ViewController A, der ein Suchfeld und eine Tabellenansicht enthält.
- ViewController B, der zum Anmelden in der App verwendet wird.
Der Ablauf ist wie folgt:
- Der Benutzer ist nicht angemeldet.
- A wird auf den Stapel geschoben. In viewWillAppear
Ich überprüfe, ob der Benutzer angemeldet ist und wenn ja, wird eine asynchrone Netzwerkanforderung gestellt, und sobald dies erledigt ist, wird die Tabelle mit den Daten aus dem Netzwerk geladen. Da der Benutzer zu diesem Zeitpunkt jedoch nicht angemeldet ist, ist die Tabellenansicht leer.
- Der Benutzer tippt auf das Suchfeld. weil er nicht eingeloggt ist, wird B gedrückt (nach einer Bestätigung);
- er meldet sich erfolgreich in B an, drückt dann eine Taste, die B öffnet und A wieder anzeigt;
- zu diesem Zeitpunkt, weil er angemeldet ist, viewWillAppear
mache ich die asynchrone Anfrage;
- Wenn das erledigt ist, rufe ich reloadData
die Tabellenansicht auf.
Was mir auffällt ist, dass numberOfRowsInSection:
es aufgerufen wird und das richtige Ergebnis zurückgibt, danach jedoch cellForRowAtIndexPath:
NICHT aufgerufen wird und die Tabelle leer bleibt.
Ich habe geprüft und reloadData
wird im Haupt-Thread aufgerufen.
Irgendeine Idee was kann es sein? Weil es mich verrückt macht!
Danke,
S.
EDIT: Hier ist das asynchrone Codebit aus viewWillAppear
A.
if ([User isLoggedIn]) {
[self.asyncRequest fetchDataWithCompletionHandler:^(id response, NSError *error) {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
if (error) {
[Utils displayError:error];
} else {
self.array = response;
self.isLoaded = YES;
[self.tableView reloadData];
[self.tableView setContentOffset:CGPointMake(0.0f, 0.0f) animated:NO];
}
}];
}
Ich habe überprüft, ob die asynchrone Anforderung erfolgreich abgeschlossen wurde und response
die richtigen Daten enthält (dies ist das Array , das zum Sichern der Anforderung verwendet wird UITableView
).
Danach reloadData
habe ich einen Haltepunkt eingefügt tableView:numberOfRowsInSection:
und dieser stoppt dort und gibt die richtige Anzahl von Elementen zurück array
. Danach wird der Haltepunkt in tableView:cellForRowAtIndexPath:
jedoch nie mehr erreicht.
quelle
tableView:cellForRowAtIndexPath:
nichtcellForRowAtIndexPath:
.Antworten:
Ein gültiges Szenario dafür, warum
numberOfRowsInSection
aufgerufen, abercellForRowAtIndexPath
nicht aufgerufen wird, ist, wenn für die Größe oder Positionierung der Tabelle keine Zeilen angezeigt werden müssen.Angenommen, Sie hatten eine Tabelle mit einer Höhe von 20 Pixel, aber der Header für den ersten Abschnitt war 30 Pixel hoch, und Sie haben für den Header null zurückgegeben (oder nicht implementiert
viewForHeaderInSection
). In diesem Fall werden keine Zeilen angezeigt und es sieht so aus, als ob die Tabelle einfach nicht vorhanden ist.Ich sehe, Sie verwenden IB. Die Größe der Tabelle kann in IB irreführend sein, da Kopf- und Fußzeilengrößen angenommen werden. Ich würde den Frame für die Tabelle protokollieren, damit Sie verstehen, wo er sich befindet, wenn die Anwendung ausgeführt wird (und wo er in IB angezeigt wird). Ich würde auch sicher sein, den Rahmen der Tabelle manuell zu dimensionieren und zu positionieren, bevor ich reloadData aufrufe. Dies löst diesen gültigen Fall, in dem
cellForRowAtIndexPath
nicht aufgerufen wird.quelle
nil
? Sprechen Sie darüber, ob einer implementiert hatheightForHeaderInSection
und 30 zurückgibt, aber dann für denviewForHeaderInSection
zurückgekehrt istnil
?Stellen Sie sicher, dass das
numberOfSectionsInTableView
nicht 0 zurückgibt.- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return 1; }
quelle
Ich hatte genau das gleiche Problem und das Problem war, dass ich versuchte, reloadData aufzurufen: von einem anderen Thread. Die Lösung wäre:
dispatch_async(dispatch_get_main_queue(), ^{ [self.tableView reloadData]; });
quelle
Wenn Sie wie ich eine andere dataSource verwenden, stellen Sie sicher, dass Sie die dataSource beibehalten. Es reicht nicht aus, nur die Klasse zu instanziieren, die die dataSource sein wird, und sie über zuzuweisen,
tableView.dataSource = myDataClass
da die dataSource-Eigenschaft einer tableView schwach ist und nach Abschluss von viewDidLoad freigegeben wird. Alle anderen Methoden wurden für mich aufgerufen - auch überraschenderweiseheightForRowAtIndexPath
-, so dass ich einige Zeit zum Debuggen brauchte.quelle
heightForRowAtIndexPath
es ist im Delegierten, deshalb wurde es sowieso aufgerufen.// For others showing up on this questions via Google, etc. // Check and make sure you've set the table view's data source and delegate. self.tableView.dataSource = self; self.tableView.delegate = self;
quelle
Wenn eine Tabellenansicht in einer Ansicht, die in Konflikt mit der Scrool-Ansicht steht, nicht aufgerufen wird. Sie sollten die Ansichten in Ihrem Storyboard oder Ihrer * .xib-Datei trennen.
// True ▼ View ► Table View ► Scrool View ► Constraints // False ▼ View ► Scrool View ► Table View ► Constraints
quelle
Wir hatten das gleiche / ähnliche Problem. Der Code erreichte
numberOfSections
undnumberOfRowsInSection
(und gab sogar Werte zurück), konnte aber nicht erreichencellForRowAt
. Zu diesem Zeitpunkt gab es in der Tabellenansicht im Storyboard nur Einschränkungen für die rechte Seite, die linke Seite und die Oberseite, nicht jedoch für die Unterseite. Nachdem wir dem unteren Rand eine Einschränkung hinzugefügt hatten, funktionierte es wie ein Zauber.Überprüfen Sie daher, ob Sie alle erforderlichen Einschränkungen für die Tabellenansicht angeben.
quelle
Alle reden immer über Größe, aber meine
TableView
in einerStackView
mit führenden Ausrichtung endete mit 0 Breite.Stellen Sie sicher, dass Sie mit überprüfen, ob Ihre
TableView
Größe korrekt istDebug View Hierarchy
.quelle
cellforrowatindexpath
. Zu Ihrer Information, es ist eine Tabellenansicht in einer UIView ...Ich habe das Problem gelöst, weil meine Unteransicht, zu der ich die hinzugefügt habe,
UITableView
nicht zugewiesen wurde, sodass sie nicht zurückgegeben wurde und die Tabellenansicht nicht anrief,cellForRowAtIndexPath
sondernnumberOfRowsInSection
aufgerufen wurdequelle
Wenn Sie wie ich das automatische Layout verwenden und der Ansicht Ihres View Controllers eine Tabellenansicht hinzufügen, stellen Sie sicher, dass Sie diese Zeile hinzugefügt haben, wenn Sie Ihre Tabellenansicht zuweisen.
tableView?.translatesAutoresizingMaskIntoConstraints = false
Dummer Fehler von meiner Seite.
quelle
Ich verwende eine Kundendatenquelle und sie wurde freigegeben. Weil es eine schwache Referenz der Tabellenansicht ist.
quelle
Das ist peinlich und verwirrend, aber hier ist meine Lösung.
Mein Code:
_scanResultTable.delegate = self; _scanResultTable.dataSource = self; // self's lifecycle was fine, wasn't getting released [_scanResultTable reloadData];
Der seltsame Teil ist also: Der Bezeichner _scanResultTable wurde in meinem Code nie irgendwo im Projekt deklariert. Ich habe keine Ahnung, wie dies kompiliert wurde (und ich habe es mehrmals neu kompiliert).
Meine Hauptursache war, dass ich meine Tabellenausgabe
scanResultTable
in meinem ViewController verknüpft hatte, sie aber als _scanResultTable bezeichnete. Sobald ich anfing, so zu verwenden,scanResultTable
wie ich es hätte tun sollen, klärten sich die Dinge auf. Ich frage mich daher, ob Objective-C etwas Besonderes daran hat, Unterstriche in Bezeichnern zu führen ...Edit: Das tut es ! Guter Herr, ich kann es kaum erwarten, diese Sprache nie wieder zu berühren.
quelle
Verschwendete Stunden und fand dann heraus, dass sich meine Tabellenansicht in einer Stapelansicht befand. Sobald ich die Stapelansicht entfernt hatte, funktionierte es wie ein Zauber. Für mich ist es Xcode 11.3.
quelle
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Make sure self.data isn't nil! // If it is, you'll always return 0 and therefore // cellForRowAtIndexPath will never get called. return [self.data count]; }
quelle
Ich benutze ReactiveCocoa. Also habe ich das Modell für die Tabellenansicht erstellt. Die Daten wurden für die Anzeige vorbereitet
numberOfRows
und so weiter. Aber ich habe die Tabellenansicht nicht als Unteransicht hinzugefügt, dahercellForRowAtIndexPath
wurde sie nicht aufgerufen)))quelle
In meinem Fall hatte ich das
TableView
Innere einesStackView
. Wenn ich es außerhalb von StackView platzierte, funktionierte es.quelle
Sind Sie sicher, dass nach dem Anmelden des Benutzers und dem Popup von B die
viewWillAppear
Methode in A aufgerufen wird, um die Aktualisierung durchzuführen?Wenn Sie B als modalen Controller anzeigen, haben Sie den nicht, wenn Sie ihn schließen
viewWillAppear
Methode aufgerufen.Soweit ich weiß,
viewWillAppear/viewDidAppear
(und ähnliche) sind Ereignisse, die vom UINavigationController bei Navigationsereignissen (Push / Pop-Viewcontroller) generiert werden. Vielleicht erhalten Sie deshalb irgendwann Ihre Aktualisierung, wenn Sie A verlassen und zurückkehren ... alles hängt davon ab, wie der nächste Viewcontroller angezeigt wird.quelle
Versuchen Sie, neue Zeilen manuell einzufügen, anstatt
[self.tableView reloadData]
:[self.tableView beginUpdates]; for (int i = 0; i < responseArray.count; i++) { _rowsNumber += 1; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0]; [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationBottom]; } [self.tableView endUpdates];
In der dataSource-Methode wird die Rückgabe inkrementiert
int _rowsNumber
:- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return _rowsNumber; }
quelle
Ich habe das gleiche Problem gelöst, indem ich die tableViewCell-ID überprüft habe. Gehen Sie zu Attributes Inspector und sehen Sie sich den Abschnitt mit den Bezeichnern an. Vermutlich fehlt. Schreiben Sie also die Zellenkennung.
quelle
Gleicher Fall hier, aber es war ein Fehler:
Ich habe eine Bildlaufansicht mit 2 Tabellenansichten in einen ViewController eingefügt (Entwurfsanforderungen), im Bildlaufansicht-Controller habe ich die ViewController (die die Tabellenansichten enthalten) programmgesteuert erstellt und eine schwache Variable zum Speichern verwendet, schlechte Idee da sie am Ende von veröffentlicht wurden viewDidLoad-Methode.
Wenn Sie den Inhalt Ihrer Tabellenansicht nicht sehen, überprüfen Sie bitte, ob er veröffentlicht wurde.
Mein Fehler war für mich sehr hirnschmerzhaft, da alle Methoden (Delegat & Datenquelle) außer viewForCell aufgerufen wurden ...
quelle
Ich habe das gleiche Problem, ich habe die Tabellenansicht in der StackView und der Tabellenansicht verwendet, um die Bildlaufbeschränkung zu deaktivieren und festzulegen, aber danach
tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
Nicht funktioniert, hören Sie auf, diese Methode alle
Data Source
und aufzurufenDelegate
stellen Sie sie richtig ein.Wenn Sie dasselbe Problem haben wie Lösung, wird die Tabellenansicht unten als führende, nachfolgende Einschränkung festgelegt
quelle
Keine der Antworten hier hat mir geholfen.
Ich habe meine Einschränkungen programmgesteuert ausgeführt, aber vergessen zu schreiben:
myTableView.translatesAutoresizingMaskIntoConstraints = false
quelle
Stellen Sie sicher, dass Ihre Einschränkungen korrekt sind und keine davon beim Erstellen entfernt wird.
quelle
Dies ist vielleicht zu offensichtlich, aber in meinem Fall habe ich ein Element (Label) gelöscht, das programmgesteuert auf den oberen Rand meiner Tabelle verweist. Es war also kein Problem mit dem Delegaten / der Quelle, sondern mit der Tabelle, die einige Probleme mit dem Inhalt hatte. Größe / Höhe, dieser Konflikt verursachte ein seltsames Verhalten und rief numberOfRowsInSection auf, aber nicht cellForRowAt indexPath
quelle