[Résolu] UITableView et cellules autosizable via Autolayout

LeChatNoirLeChatNoir Membre, Modérateur
novembre 2014 modifié dans API UIKit #1

Salut,


 


Je continue ma conversion à  Autolayout et me heurte à  un écueil...


Dans une vue que j'ai créer dans IB, je vais devoir ajouter des sous-vues.


 


Ces sous vues, je n'en connais pas la nb a priori et elles vont venir s'empiler les unes sous les autres.


 


Sans mon viewWillAppear, je m'occupe donc de peupler cette vue.


 


Je commence par déclarer ma sousVue1, je l'ajoute à  ma vue et ensuite, je fais un AddConstraints.


 


Pb => il crash en me disant : 


 


When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.


 

Je comprends que c'est un pb de timing. J'ajoute ma vue dans la hiérarchie mais il faudrait attendre 1 cycle avant d'ajouter les contraintes...

 

Je me tourne donc vers la doc et je comprends qu'il faut le faire dans la méthode 

 

-(void)updateViewConstraints

 


Seulement voilà ... Il faudrait que je garde une référence vers ttes mes sous vues... Lourdeau !

 

C'est où que j'ai loupé un truc ?


Réponses

  • AliGatorAliGator Membre, Modérateur
    Es-tu sûr que tu ajoutes tes contraintes à  la bonne vue, déjà  ? Il faut faire le addConstraints sur l'ancêtre commun aux vues concernées par les contraintes.


    Et sinon, si tu mets plutôt ton code dans le viewDidAppear est-ce que ça ne résoudrait pas le problème ?
  • Joanna CarterJoanna Carter Membre, Modérateur

    Pourquoi crées-tu les sous-vues en code ? On peut tout faire dans un storyboard ou un xib.


  • AliGatorAliGator Membre, Modérateur


    Pourquoi crées-tu les sous-vues en code ? On peut tout faire dans un storyboard ou un xib.




    Il ne peut pas, parce que :




     


    Ces sous vues, je n'en connais pas la nb a priori [...].



  • Joanna CarterJoanna Carter Membre, Modérateur
    Dans ce cas là , je demanderais pourquoi pas utiliser quelque chose comme UICollectionView ? :)
  • AliGatorAliGator Membre, Modérateur
    Bah si les vues sont toutes différentes et n'ont rien à  voir c'est pas forcément adapté une CollectionView... ça dépend du besoin...


    Par exemple, si c'est pour faire un peu comme la palette d'inspecteur de Xcode, pour empiler les différentes sections de réglages de la vue sélectionnée en fonction des réglages disponibles et de la chaà®ne d'héritage, empiler des vues avec AutoLayout est plus adapté qu'une CollectionView non ?
  • LeChatNoirLeChatNoir Membre, Modérateur

    non, non...


    Les sous vues seront identiques. 


    Je veux dire, les infos à  l'intérieur changeront mais les sous-vues sont les mêmes.


     


    En gros, ça serait une liste de topos, avec une imageView, un titre et un bouton.


    Me dites pas qu'il faut que je fasse une UITableView ?


  • CéroceCéroce Membre, Modérateur

    On ne te le dit pas, mais tu cherches un peu à  te compliquer la vie, quand même. ;-)


    Si toutes les sous-vues sont disposées pareil, alors une Table View c'est quand même ce qu'il y a de plus simple à  coder.


  • LeChatNoirLeChatNoir Membre, Modérateur
    octobre 2014 modifié #9

    en fait, dans 95% des cas, y aura qu'un topo... Mais parfois, le site est tellement grand qu'il y a un topo par secteur... Donc dans ce cas, je présente les différents topos...


     


    Bon ok... Je vais faire une tableview... 


     


    M'enfin, une TableView qui scrollera pas....


     


    [edit]


    A bien y réfléchir, vous avez raison... Une tableView ou collectionView est faites pour ça...


    Je n'utilise pas Storyboard mais je peux définir quand même une UITableViewCell dans mon xib avec ttes les contraintes qui vont bien. Et hop.


     


    C'est cool.


    Ca répond pas à  la question initiale mais bon...


    Merci à  tous !


    [/edit]


  • LeChatNoirLeChatNoir Membre, Modérateur

    Salut,


     


    Du coup, je pars sur une UITableView. Mais bonjour l'angoisse...


     


    Mes UILabel n'ont pas tous la meme hauteur...


    Du coup, comment avoir une tableView avec des cell qui se resize ?


     


    Réponse : http://stackoverflow.com/questions/18746929/using-auto-layout-in-uitableview-for-dynamic-cell-layouts-variable-row-heights


     


    Pfffff..... C'est d'une simplicité...


    La complexité du calcul des frames sans autolayout de l'ancien temps se retrouve finalement ailleurs...


  • LeChatNoirLeChatNoir Membre, Modérateur

    Alors alors :)


     


    J'avance.


    Grâce au code issu du lien précédent, j'ai ma tableView qui dimensionne la hauteur de ses cellules dynamiquement.


    Ca, c'est fait.


     


    Maintenant, ma tableView n'occupe pas toute ma window. Et je l'utilise uniquement pour afficher une liste d'éléments à  peu près identiques. La notion de scroll ne m'intéresse pas ici.


     


    J'aimerai donc que la tableView se dimensionne en hauteur pour "embrasser" toute sa contentView.


     


    Pour ce faire, je pense utiliser -didLayoutSubviews de mon controller et d'y ajouter un bout de code pour aller altérer la contrainte "Height" de la tableView.


     


    Ca vous parait approprié ?

  • LeChatNoirLeChatNoir Membre, Modérateur

    Je me répond à  moi-même suite à  mes investigations.


     


    Les cellules de ma TableView se dimensionnent bien dynamiquement et je recommande donc le code du lien sus-cité qui fonctionne bien en iOS7 ET iOS8.


     


    Pour dimensionner ma TableView à  la taille de sa contentView, j'update donc la contrainte hauteur dans la fonction didLayoutSubviews :



    -(void)viewDidLayoutSubviews
    {
    CGFloat height = self.tvInfos.contentSize.height;

    if (self.infosTvHeight.constant!=height && height>0) {
    self.infosTvHeight.constant = height;
    [self.view layoutIfNeeded];
    [self.view updateConstraintsIfNeeded];
    }
    }

    Mais sous iOS7, ça ne suffit pas car lors des rotations, le didLayoutSubview semble appelé trop tôt (la contentSize n'est pas encore modifiée).


     


    J'ai donc ajouté le même bout de code dans la méthode didRotateFromInterfaceOrientation:


     


    Voilà  ;)


  • LeChatNoirLeChatNoir Membre, Modérateur

    Je continue ma refonte d'écran et la solution des UITableView est clairement le meilleur conseil que vous m'ayez donné !


     


    Tout s'éclair et se simplifie !


     


    Merci o:)


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