TableView Cell NSNotification

  • TableView Cell NSNotification

    Hi,

    ich bin am verzweifeln und hoffe, Ihr könnt mir helfen. Google konnte es nicht. Ich habe folgendes Problem: Ich empfange Daten von einem Sensor über Bluetooth. Das klappt ganz gut. Dies geschieht in den eine Controller. Dann habe ich mir zwei Container-ViewController erstellt, die ein TableViewController enthalten (aus Design-Gründen) und registriere die Zellen zum empfangen einer NSNotification. Jedesmal, wenn ich z.B. Lichtwerte empfange wird die passende Notification ausgelöst und soll empfangen werden. Soweit die Theorie.

    Das ganze läuft auch solange man nicht Scrollt oder die Werte ändert. Wenn ich jetzt z.B. ins Menü gehe und sage ich will Licht mehr angezeigt haben sondern Temperatur, das speichere und dann den TableView neu lade, bekomme ich nichts mehr angezeigt bzw. wenn ich es anders programmiere mehre Werte sekündlich wechselnd.

    Ich habe rausgefunden, dass das daran liegt, dass der TableView die Zellen ja reused. Also habe ich als erstes probiert mich beim didEndDisplayCell da wieder unzuregistrieren und dann in cellForRowAtIndexPath wieder zu registrieren. Das war mäßiger Erfolg. Als nächstes habe ich direkt in cellForRowAtIndexPath versucht mich als erstes zu deregistrieren und dann wieder zu registrieren. Das ganze läuft aber nur bis ich 2-3 mal gescrollt habe.

    Bei beiden Methoden tritt dann das Phänomen auf, dass man für nichts mehr registriert ist und nichts mehr angezeigt wird.

    Wie kann ich das beheben? Wie man das Reusen ausstellen kann trotz dessen, dass man Storyboard, habe ich noch nicht rausfinden können. Geht das überhaupt? Klar kostet es mehr Speicher aber maximal können 10 Zellen angezeigt werden, da es nur 10 Sensor Werte gibt - also da hält sich das in Grenzen. Was kann man noch machen? Hatte jemand schon mal das Problem?

    Viele Grüße und euch einen schönen Sonntag
    Nils
  • Hallo Nils,

    warum soll die Zelle auf Nachrichten für Änderungen hören?
    Lass das doch den TableViewController machen und der gibt das entsprechend an die Zelle oder das TableView weiter.

    Meiner Meinung nach wäre es sogar besser ein -representedObject zu setzen.

    Dann kann die Zelle die Werte selbst holen, wenn der Controller ein -update schickt.
    Und das sendet er auf Grund ein Delegate/Benachrichtigung vom Bluetooth-Controller.

    Viele Grüße
  • Vielleicht habe ich es nicht ganz durchschaut, aber warum lässt Du nicht den UITableViewController die Nachrichten observieren und ihn dann die Zellen aktualisieren? Wäre als Controller doch eh sein Job...

    Mattes

    P.S.: Ups, zu langsam :D
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • Mal davon abgesehen, dass die beiden über mir natürlich recht haben, so kann man dein Problem natürlich auch beheben indem du den Zellen einen ihrer notification entsprechenden identifier gibst. Also lichtzellen haben einen anderen identifier als Temperaturzellen.

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • AppleDeveloper schrieb:

    Wie man das Reusen ausstellen kann trotz dessen, dass man Storyboard, habe ich noch nicht rausfinden können. Geht das überhaupt?
    Zum eigentlichen Problem wurde ja schon alles gesagt, daher nur kurz zum Thema „reuse“. Ja, man kann das „ausstellen“. Es gibt zwar keinen Schalter dafür, aber niemand hindert dich daran, für jeden IndexPath eine Zelle zu erzeugen. Du musst dann die Zuordnung der Zellen zum IndexPath halt selbst verwalten.
    Wenn du aber sowieso nur eine kleine, konstante Anzahl an Zellen hast, ist eine statische Tabelle vielleicht auch eine Überlegung wert.
  • Danke für eure ganzen Antworten!

    Ich komme bedingt durch Umzug leider erst jetzt wieder dazu.

    Irgendwie habe ich da einen kleinen Denkfehler und ich hoffe, ihr könnt da Licht ins Dunkle bringen.

    Also: Ich dachte eigentlich ich hätte das MVC Modell umgesetzt. Denn die App hat ein etwas anderes Design. Also es ist eine iPad App, die nur im Querformat geht. Der Bildschirm ist horizontal in zwei Teile geteilt. Dies geschieht über zwei Container Controller.

    In dem unteren Container Controller (nennen wir ihn Main) befindet sich der View für die Steuerung. Weiterhin habe ich links und rechts von dem Steuerungsview zwei weitere Container-Controller hinzugefügt, die die Daten anzeigen sollen. Das sind die zwei TableViews.

    Nun hat man Einstellungen und kann sagen Wert A anzeigen, Wert B nicht etc. Also hat man einige Möglichkeiten. Die Daten werden im Model gespeichert. Wenn sich die Einstellungen geändert haben benachrichtigt das Model den Main Controller, dass sich die Einstellungen geändert haben und dieser sendet dann "reloadTableView" an die beiden TableViewController. Das läuft wie folgt ab: Gehen wir davon aus, dass 3 Werte angezeigt werden sollen. Dann bekommt der eine TableViewController 2 Werte, der andere 1. Bei 4 Werten geht es ja schön auf, da bekommt jeder 2. Die Daten holen die sich aus dem Model. Also statisch geht ja gar nicht, da sich die Aufteilung immer ändert.

    Der Main-Controller hat von dem Sensor-Framework das Delegate implementiert und wird benachrichtigt, wenn sich irgendein Sensor ändert. Er prüft, ob der überhaupt angezeigt wird, wenn ja wertet der den aus und sendet dann die Benachrichtigung an die TableViewCell.

    Das läuft aber wie geagt nur bis zum scrollen oder Daten ändern.

    Ist das denn nicht das MVC-Model, so wie ich es gemacht habe?

    Das mit den mehreren Identifier wäre eine Idee aber irgendwie unschön. Sind ja alles die gleichen Zellen.

    Wenn das was ich umgesetzt habe totaler Blödsinn ist, würde ich mich gerne über Tipps freuen!
  • So ganz verstehe ich Dein Konstrukt nicht.

    Wenn Du die Daten im Model hast, dann sollte doch irgendwo eine Liste existieren mit allen Objekten die die Tableviews anzeigen müssen. Aus dieser Liste holst du dir dann das passende Object in cellForRowAtIndexPath raus und zeigst es an. Dann giobt es auch keine Probleme mit irgendwelchem Reuse.

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • AppleDeveloper schrieb:

    Also: Ich dachte eigentlich ich hätte das MVC Modell umgesetzt.



    Der Main-Controller hat von dem Sensor-Framework das Delegate implementiert und wird benachrichtigt, wenn sich irgendein Sensor ändert. Er prüft, ob der überhaupt angezeigt wird, wenn ja wertet der den aus und sendet dann die Benachrichtigung an die TableViewCell.

    Genau hier fehlt Dir der Controller im MVC Modell. Das Model oder der Main-Controller sendet keine Benachrichtigungen über Änderungen direkt an Views, welche die Daten anzeigen. Das Model oder der Main-Controller sendet ggf. Benachrichtigungen an andere, an den Daten interessierte, View Controller, welche daraufhin die Daten in den Views aktualisieren.

    Ok, eigentlich könnten sich auch Views direkt über Änderungen an den Daten benachrichtigen lassen. Bei Table- und/oder CollectionViewCells sollte dies jedoch alles über die DateSource laufen, da die Zellen reusable sind. Neben reloadData gibt es ja auch die Methode reloadRowsAtIndexPaths:withRowAnimation:, um nur einzelne Rows in einem TableView zu aktualisieren. Der TableView entscheidet dann eigenständig, ob ein Update der Zelle überhaupt erforderlich ist, weil diese sichtbar ist, oder nicht.

    BTW: Wenn Du die Daten z.B. über Core Data verwaltest, dann kannst Du Dir über einen NSFetchedResultsController die Logik und den Aufwand für die Benachrichtigung über Änderungen an den Daten komplett sparen. Der NSFetchedResultsController erkennt automatisch Änderungen an "seinen" Daten und Informiert darüber über Methoden im NSFetchedResultsControllerDelegate Protocol.
  • Danke, verstehe ich soweit! Man muss jedoch noch erwähnen, dass diese Daten nicht gespeichert werden. Bringt ja nichts. Das sind ja alles live Daten die je nach Sensor eine Sekunde bis zu paar Minuten gültig sind. Luftfeuchtigkeit ändert sich eigentlich kaum aber der Gyro-Sensor oder der Magnet-Sensor sekündlich.

    Dann habe ich es jetzt verstanden: Es wäre also am besten, wenn ich alle Daten in der Datasource Update und nur die Datasource die Daten kennt. verstehe ich das richtig? Das habe ich damals nicht so programmiert, weil ich dachte, dass es flackert und vor allem Speicheraufwändiger ist also immer nur die Labels direkt upzudaten.

    Zurzeit wird der TableView nur bei Einstellungsänderungen reloaded und sonst geht es über die Notifications