TableView et instantiation

chimeradechimerade Membre
mai 2014 modifié dans Dev. iOS, watchOS, tvOS #1

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...


Mots clés:

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éroceCéroce Membre, Modérateur

    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.


  • denis_13denis_13 Membre
    mai 2014 modifié #5

    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 ;)

  • CéroceCéroce Membre, Modérateur
    mai 2014 modifié #8

    pourquoi allouer 4 fois la MEME cellule ? (démarrage)

    Au début la table est vide. Il faut instancier assez de cellules pour couvrir toute la surface visible de la table. Je précise qu'il ne s'agit pas de la _même_ cellule, mais de 4 instances de la même classe (ou du même prototype si on utilise un storyboard).
     

    puis pourquoi allouer UNE AUTRE fois la MEME cellule  lors du 1er scroll ?

    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.
     

    Puis pourquoi ne plus les allouer ...

    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



Connectez-vous ou Inscrivez-vous pour répondre.