TableView et instantiation
bonjour à tous,
je suis nouveau sur le forum, voici mon pb :
J'utilise des cellules prototypes (5)+ storyboard
dans le cellForRow :
Activities_UpS_U *cell = [tableView dequeueReusableCellWithIdentifier:kActivityUpS_U forIndexPath:indexPath];
[cell setupWithElement:_element];
return cell;
je m'interrogeais sur le fait que systématiquement le setup est appelé alors qu'en fait une fois suffit.
Donc plutôt que d'utiliser une méthode du mon TabelViewCell (setupWithElement) appelée depuis mon controller, je me disais qu'il pourrait être mieux de le faire dans awakefromnib (ou initwithcoder)
- sachant que si j'y arrive... le pb suivant sera de passer _element qui est un NsDictionary
Mais là , je ne comprends pas du tout l'instanciation des cellules : lors de l'affichage, 4 cellules sont visibles et le awakefromnib est appelé 4 fois (normal) le scroll vers le bas rend la 5eme visible et de nouveau Awake appelé (tjrs normal) puis à partir de la 6ème le prepareForReuse seul est appelé comme si il n'avait pas besoin de l'instancier, avec un contenu qui est le même qu'une cellule précedemment affichée.
Pour plus d'informations, je précise qu'il s'agit des 6 premières cellules du MEME type.
Je ne comprends pas pourquoi la 1ère fois qu'une cellule est appelée l'instantiation n'est pas systèmatique alors que c'est le cas pour les 4 visibles puis la 1ère scrollée ...
Rien ne différencie la 7ème de la 6ème qui se voit pourtant "réutilisée" et non allouée
Si quelqu'un peut me mettre sur une piste je vous remercie bien !
A défaut si vous avez une autre solution pour tester dans le controller comment ne pas effectuer 2 fois le setup...
Réponses
Bonjour,
en général tu utilise dequeueReusableCellWithIdentifier pour passer des arguments à ta cellule, la partie d'initialisation de ta cellule qui ne dépend pas de tes arguments tu peux probablement la mettre dans initWithCoder:
Merci de ta réponse,
mais c'est le 2ème point de ma question qui viendra une fois que j'aurai trouvé pourquoi le initWithCode (ou AwakeFromNib) n'est déclenché que sur certaines cellules (bloquant pour la suite)
C'est parce que -dequeueReusableCell... comme son nom l'indique, renvoie une cellule à recycler, c'est à dire qui était auparavant dans la table mais qui ne l'est plus, et qu'on va pouvoir réutiliser. Elle a été conservée pour éviter de l'instancier à nouveau, ce qui améliore les performances.
Au départ, il n'y a pas de cellule à recycler, c'est pourquoi -dequeueReusableCell... les instancie, et appelle donc leurs méthode -init.
Voir le Table View Programming Guide.
pas grand chose à rajouter sur ce qu'à dit Céroce, ce système évite de créer et de détruire des cellules inutilement (opérations très coûteuses en resources) à chaque fois que que tu fais défiler les données de ton tableau. Si ton data source a 10000 valeurs à exposer mais ta table n'affiche que 6 cellules simultanément, seules 6 allocations de cellules sont réalisées, ensuite en configurant tu mets à jours les valeurs qui ont changé d'une cellule à l'autre (donc il est plutôt rare que l'on ait à ajouter du code dans l'initialiseur de la cellule).
au fait tant qu'on en parle...
tu devrais lire cet article
http://inessential.com/2012/12/31/uitableviewcell_is_not_a_controller
quand on l'a peu pratiqué, on a du mal à garder en tête les contraintes qu'impose le recyclage des cellules... en particulier, le fait que c'est assez délicat d'y avoir du code qui lance des tâches asynchrones, car au moment où les données arrivent ben elles ne correspondent peut-être pas à l'objet que tu aimerais afficher.
Donc l'idée (exposée dans l'article) est d'éviter d'ajouter un objet metier à une cellule mais de configurer la cellules avec les valeurs que l'on veut afficher (j'arrête là car c'est une boite de pandore ... :-) )
merci à vous pour vos réponses mais j'ai toujours un vide ... je comprends bien qu'il réutilise une celle déjà allouée (c'est le but... mais dans ce cas pourquoi allouer 4 fois la MEME cellule ? (démarrage)
puis pourquoi allouer UNE AUTRE fois la MEME cellule lors du 1er scroll ?
Puis pourquoi ne plus les allouer ...
Si on imagine 10 éléments MyCellClass dont 4 prendront le focus à l'affichage. Pourquoi ne pas instancier la 1ère cellule et réutiliser TOUT le reste ?
Dans mon cas (désolé je me répète) 4 alloc puis scroll puis 1 alloc puis reuse ..
encore merci pour votre aide et je vais lire avec attention ton doc denis_13
Parce qu'on doit afficher une nouvelle ligne, alors il faut une nouvelle cellule pour la couvrir, or on n'en n'a pas encore en réserve. Par contre, la cellule qui disparaà®t n'est pas détruite, mais est gardée en réserve.
Parce que la table dispose d'une cellule en réserve, alors elle te la renvoie.
Pour être précis, ce n'est pas tant l'instanciation de la cellule elle-même qui est lourde, c'est plutôt qu'une NSTableViewCell contient pas mal de sous-vues, et la création de cette hiérarchie est lourde.
ok céroce merci pour l'explication