Wozu der reuseIdentifier bei UITableView cells?

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Wozu der reuseIdentifier bei UITableView cells?

    also ich sage einer tableview welche cell-klasse sie verwenden soll:

    Quellcode

    1. ​[this.table registerClass:[UITableViewCell class] forCellReuseIdentifier:@"WTF"];


    In der "cellForRowAtIndexPath" methode hole ich dann eine cell von der tableview ab:

    Quellcode

    1. ​UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"WTF"];


    warum zum teufel muss ich da 2 mal einen identifier angeben?
    unter iOS hat eine tableview ja nureine column (sonst würde man die cell ja nicht an die tableview hängen sondern an die columns).
    somit frage ich mich warum ich den verdammten identifier angeben MUSS.

    übersehe ich irgendwas?

    danke
  • Du kannst mehrere Klassen für mehrere Identifier in registerClass:forCellReuseIdentifier: registrieren.
    Um schlussendlich die richtige Instanz zu bekommen musst Du angeben, für welchen Identifier Du die Zelle haben möchtest.

    Ist auf den ersten Blick dämlich, wenn man nur eine Klasse registriert.
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Marco Feltmann schrieb:

    Du kannst mehrere Klassen für mehrere Identifier in registerClass:forCellReuseIdentifier: registrieren.
    Um schlussendlich die richtige Instanz zu bekommen musst Du angeben, für welchen Identifier Du die Zelle haben möchtest.

    Ist auf den ersten Blick dämlich, wenn man nur eine Klasse registriert.


    ja aber ich brauche das nicht (wie wahrscheinlich auch alle anderen in 99% der fälle) also warum wird mir nicht erlaubt das nicht anzugeben. oder einen leeren string.

    wird das etwas nicht pro tableview gespeichert sondern für ALLE tableviews?
    das kann ich mir irngendwie nicht vorstellen? somit würde es ja zu problemen kommen wenn man für verschiedene tableviews den gleichen identifier für verschiedene cell-klassen verwendet (oder darf man das gar nicht?)
  • macmoonshine schrieb:

    gritsch schrieb:

    ja aber ich brauche das nicht (wie wahrscheinlich auch alle anderen in 99% der fälle) also warum wird mir nicht erlaubt das nicht anzugeben. oder einen leeren string.

    Ich hatte schon mehrere Projekte, wo ich unterschiedliche Zelltypen gebraucht habe. Ich finde diesen Mechanismus sehr sinnvoll.


    ja aber normalerweise braucht man das doch nicht. warum zwingt einen apple dann eine unique-id zu verwenden?
  • also normalerweise sag ich doch einer tabelle welche klasse bzw welches nib die cellen haben sollen. dass verschiedene rows dieser tabelle verschiedene cell-klassen haben sollen ist doch eher die ausnahme!?

    ich hab mal schnell eine UITableView-Addion gezimmert. ob man das mit dem eindeutigen identifiert braucht bin ich mir nicht sicher oder ob man einfach irgendeinen string angeben kann.

    Quellcode

    1. ​//
    2. // UITableViewAdditions.h
    3. //
    4. // Created by Gabriel Gritsch on 16.06.14.
    5. //
    6. //
    7. #import <Foundation/Foundation.h>
    8. @interface UITableView (Additions)
    9. - (void)registerPrototypeCellClass:(Class)cellClass;
    10. - (void)registerPrototypeCellNib:(UINib *)nib;
    11. - (id)dequeueReusableCell;
    12. @end
    Alles anzeigen

    Quellcode

    1. ​//
    2. // UITableViewAdditions.m
    3. //
    4. // Created by Gabriel Gritsch on 16.06.14.
    5. //
    6. //
    7. #import "UITableViewAdditions.h"
    8. @implementation UITableView (Additions)
    9. - (NSString *)_prototypeCellIdentifier
    10. {
    11. return [NSString stringWithFormat:@"%p", self];
    12. // do we need a unique-identifier or can we simply return something like @"X"?
    13. // use objc_getAssociatedObject and objc_setAssociatedObject to store the value...
    14. }
    15. - (void)registerPrototypeCellClass:(Class)cellClass
    16. {
    17. [self registerClass:cellClass forCellReuseIdentifier:self._prototypeCellIdentifier];
    18. }
    19. - (void)registerPrototypeCellNib:(UINib *)nib
    20. {
    21. [self registerNib:nib forCellReuseIdentifier:self._prototypeCellIdentifier];
    22. }
    23. - (id)dequeueReusableCell
    24. {
    25. return [self dequeueReusableCellWithIdentifier:self._prototypeCellIdentifier];
    26. }
    27. @end
    Alles anzeigen
  • Ach so, als Identifier kannst Du irgendeinen String nehmen. Er dient nur dazu, unterschiedliche Zelltypen auseinanderzuhalten.

    Quellcode

    1. - (void)viewDidLoad {
    2. [super viewDidLoad];
    3. [self registerClass:cellClass forCellReuseIdentifier:@"Kleine Entchen"];
    4. }
    5. - (UITableViewCell *)tableView:(UITableView *)inTableView cellForRowAtIndexPath:(NSIndexPath *)inIndexPath {
    6. UITableViewCell *theCell = [inTableView dequeueReusableCellWithIdentifier:@"Kleine Entchen"];
    7. ...
    8. return theCell;
    9. }
    Alles anzeigen
    „Meine Komplikation hatte eine Komplikation.“
  • macmoonshine schrieb:

    Ach so, als Identifier kannst Du irgendeinen String nehmen. Er dient nur dazu, unterschiedliche Zelltypen auseinanderzuhalten.

    Quellcode

    1. - (void)viewDidLoad {
    2. [super viewDidLoad];
    3. [self registerClass:cellClass forCellReuseIdentifier:@"Kleine Entchen"];
    4. }
    5. - (UITableViewCell *)tableView:(UITableView *)inTableView cellForRowAtIndexPath:(NSIndexPath *)inIndexPath {
    6. UITableViewCell *theCell = [inTableView dequeueReusableCellWithIdentifier:@"Kleine Entchen"];
    7. ...
    8. return theCell;
    9. }
    Alles anzeigen


    ja aber warum zwingt mich apple dazu?
    ich brauche keine verschiedenen cell-klassen für verschiedene rows (in 99% der fälle) und ich will keine strings einfach nur so angeben denn wie schnell vertippt man sich da.
    dann kommen wieder die strings die man per #define am anfang der datei setzt. diese sind natürlich auch EVIL. also eine string-konstante welche jede menge überflüssige tipparbeit bedeutet.
    warum also muss das so kompliziert sein?
  • Es sind zwei unterschiedliche Vorgänge.
    registerClass… -> kreiere mir ein Objekt dieser Klasse für diesen Identifier, wenn Du sie in deiner Reuse-Queue nicht findest.
    dequeueReusable… -> gib mir das Objekt für diesen Identifier aus Deiner Reuse-Queue.

    Soweit ich das Konzept verstanden habe, verhindert dieser Mechanismus, dass Dir dequeueReusableCellWithIdentifier: ein nil zurück gibt. Du sparst Dir also den Vergleich auf nil.

    Spannend: während der Identifier bei registerClass… weder nil noch @"" sein darf, darf der Identifier bei dequeueReusable… nur nicht nil sein.
    Was passiert also bei folgendem Konstrukt?

    Quellcode

    1. - (void)viewDidLoad {
    2. [super viewDidLoad];
    3. [self registerClass:cellClass forCellReuseIdentifier:@"Kleine Entchen"];
    4. }
    5. - (UITableViewCell *)tableView:(UITableView *)inTableView cellForRowAtIndexPath:(NSIndexPath *)inIndexPath {
    6. UITableViewCell *theCell = [inTableView dequeueReusableCellWithIdentifier:@""];
    7. ...
    8. return theCell;
    9. }
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Marco Feltmann schrieb:

    Es sind zwei unterschiedliche Vorgänge.
    registerClass… -> kreiere mir ein Objekt dieser Klasse für diesen Identifier, wenn Du sie in deiner Reuse-Queue nicht findest.
    dequeueReusable… -> gib mir das Objekt für diesen Identifier aus Deiner Reuse-Queue.

    Soweit ich das Konzept verstanden habe, verhindert dieser Mechanismus, dass Dir dequeueReusableCellWithIdentifier: ein nil zurück gibt. Du sparst Dir also den Vergleich auf nil.

    Spannend: während der Identifier bei registerClass… weder nil noch @"" sein darf, darf der Identifier bei dequeueReusable… nur nicht nil sein.
    Was passiert also bei folgendem Konstrukt?

    Quellcode

    1. - (void)viewDidLoad {
    2. [super viewDidLoad];
    3. [self registerClass:cellClass forCellReuseIdentifier:@"Kleine Entchen"];
    4. }
    5. - (UITableViewCell *)tableView:(UITableView *)inTableView cellForRowAtIndexPath:(NSIndexPath *)inIndexPath {
    6. UITableViewCell *theCell = [inTableView dequeueReusableCellWithIdentifier:@""];
    7. ...
    8. return theCell;
    9. }


    das macht doch keinen sinn denn man verwendet doch in der regel immer die gleiche cell-klasse in einer tableview (also in ein und der selben).
    ich habe da keine 5 verschiedenen cell-klassen für unterschiedliche rows. also brauche ich nur eine instanz der cell-klasse (prototype) die ich angegeben habe.
    wenn eine instanz davon frei ist soll er mir die geben, andernfalls eine neue erstellen. wozu soll ich ihm einen idententifier angeben für eine sache von der ich in 99% der fälle keine verschiedenen brauche.
  • Michael schrieb:

    gritsch schrieb:

    ja aber warum zwingt mich apple dazu?
    ich brauche keine verschiedenen cell-klassen für verschiedene rows (in 99% der fälle)

    Vielleicht, weil Apple keine Lust hatte extra für dich den Sonderfall „nur eine Cell-Klasse“ durch zusätzlichen Code von dem Identifier zu befreien.


    warum nur für mich? das sind doch 99% der fälle dass man pro tabelle nur eine cell-klasse verwendet oder verwendet ihr für jede row eine andere klasse!??!?!?
  • gritsch schrieb:

    das sind doch 99% der fälle dass man pro tabelle nur eine cell-klasse verwendet oder verwendet ihr für jede row eine andere klasse

    Ich hatte schon mehrere Projekte, wo ich unterschiedliche Typen für Zellen brauchte. Ich sehe auch nicht das Problem. Wenn Dich die Konstante stört, nimm' doch einfach den Klassennamen beziehungsweise den des XIBs.
    „Meine Komplikation hatte eine Komplikation.“
  • Michael schrieb:

    gritsch schrieb:

    warum nur für mich? das sind doch 99% der fälle dass man pro tabelle nur eine cell-klasse verwendet

    Die 99% hast du woher?


    lass es dann eben 95 % sein aber normal braucht man pro tabelle doch nur eine cell-klasse (für die eine tabelle class A, für eine andere tabelle eben class B, aber doch allermeist nicht class A und B für eine einzige tabelle).
    und diesen spezialfall kann man ja über die identifier handeln, warum aber ist es für die große menge der fälle nicht einfach gelöst (von mir aus auch nil oder leeren string als parameter erlauben)?
    das verführt (vor allem anfänger) doch nur dazu schlechten code zu schreiben (eben an 2 stellen im code per @ einen string zu verwenden der identisch sein muss oder #defines zu verwenden...
  • Ich habe zum Beispiel eine großes Projekt wo jeder View wie ein Formular dynamisch aufgebaut wird aus unterschiedlichsten Elementen. Da ist das super praktisch einfach für jeden Elementtyp eine Cellklasse zu definieren und gut ist. Die Tableview kümmert sich um den ganzen Rest. Klar könnte man das auch mit einem Scrollview machen aber da muss man sich um den ganzen SCheiß mit den Offsets und Contentsize etc selber kümmern.

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

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

    Ich habe zum Beispiel eine großes Projekt wo jeder View wie ein Formular dynamisch aufgebaut wird aus unterschiedlichsten Elementen. Da ist das super praktisch einfach für jeden Elementtyp eine Cellklasse zu definieren und gut ist. Die Tableview kümmert sich um den ganzen Rest. Klar könnte man das auch mit einem Scrollview machen aber da muss man sich um den ganzen SCheiß mit den Offsets und Contentsize etc selber kümmern.

    Gruß

    Claus


    da verwendest du das dequeueReusable aber überhaupt nicht weil du ja für jede row deine fertige view (tableviewcell) hast.