Aller au contenu


Photo

TableView dans une TableViewCell


  • Please log in to reply
18 réponses à ce sujet

#1 Ben77650

Ben77650

    Torréfacteur de fèves

  • Membre
  • PipPipPipPipPip
  • 515 messages
  • LocationParis

Posté 03 août 2017 - 15:11

Hello,

 

Dans le cadre d'un projet au boulot je doit gérer un système assez similaire à celui de Facebook, avec un système de commentaires, et des réponses à un commentaire.

 

A savoir qu'aussi bien mon commentaire que ma réponse peuvent faire plusieurs lignes.

On m'a donc soufflé de faire une tableView pour les commentaires, avec à l'intérieur de la cellule contenant le commentaire un autre tableView contenant les réponses.

 

Le souci que cela me pose est que je n'arrive pas à faire s'afficher le texte sur le nombre de lignes nécessaire, la taille des tableView ne suivant pas.

 

Voila ci joint mon code

 

CommentViewController.m

#pragma mark - TableView delegate/datasource methods

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    CommentTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"CommentTableViewCell"];
    
    CommentModel *comment = [self.dataSource itemAtIndexPath:indexPath];
    cell.comment = comment;
    cell.delegate = self;
    cell.tableViewResponses.hidden = ![self.indexToShow containsObject:@(comment.commentId)];
    cell.responseView.hidden = [self.indexToShow containsObject:@(comment.commentId)];
    cell.dataSource = self.dataSource;
    NSString *titleButton;
    
    if([comment.answers count] == 0) {
        cell.responseView.hidden = true;
    }
    else if([comment.answers count] == 1) {
        titleButton = [NSString stringWithFormat:NSLocalizedString(@"%ld answer", @""), [comment.answers count]];
    }
    else {
        titleButton = [NSString stringWithFormat:NSLocalizedString(@"%ld answers", @""), [comment.answers count]];
    }
    [cell.nbReponseButton setTitle:titleButton forState:UIControlStateNormal];
    
    return cell;
}

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    if(indexPath.item == [self.dataSource numberOfObjectsInSection:0] - 1 && !self.noNewObjects) {
        self.page += 1;
        [self fetchComments];
    }
}

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.dataSource numberOfObjectsInSection:section];
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    UIFont *usedFont = [UIFont fontWithName:@"AvenirNextCondensed-Regular" size:18];
    
    CommentModel *comment = [self.dataSource itemAtIndexPath:indexPath];
    NSString *content = [comment.content stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    NSString *title = [content stringByReplacingOccurrencesOfString:@" " withString:@"#"];
    CGRect textViewRect = [title
                           boundingRectWithSize:CGSizeMake(self.tableView.frame.size.width - 109, CGFLOAT_MAX)
                           options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading
                           attributes:@{ NSFontAttributeName : usedFont }
                           context:nil];
    
    int height = textViewRect.size.height + 40;
    
//    if([self.indexToShow containsObject:@(comment.commentId)] && comment.answers.count != 0) {
//        return [CommentTableViewCell getHeightFromTitle:comment.content andComments:comment.answers andWith:self.view.frame.size.width];
//    }
    
    if(comment.answers.count == 0) {
        return height + 65;
    } else {
        return height + 75;
    }
    
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    CommentModel *comment = [self.dataSource itemAtIndexPath:indexPath];
    if([self.indexToShow containsObject:@(comment.commentId)]) {
        [self.indexToShow removeObject:@(comment.commentId)];
        [self.tableView reloadData];
        
        if(self.messageViewHeightConstraint.constant > 0) {
            [UIView animateWithDuration:0.5
                             animations:^{
                                 self.messageViewHeightConstraint.constant = 0;
                                 [self.view layoutIfNeeded];
                             }];
        }
    }
}

CommentTableViewCell.m

- (void)awakeFromNib {
    [super awakeFromNib];
    
    self.avatarImageView.layer.cornerRadius = self.avatarImageView.layer.frame.size.width / 2;
    self.avatarImageView.layer.masksToBounds = YES;
    
    UITapGestureRecognizer *singleFingerTap =
    [[UITapGestureRecognizer alloc] initWithTarget:self
                                            action:@selector(respondComment:)];
    [self.arrowView addGestureRecognizer:singleFingerTap];
    
    [self.tableViewResponses reloadData];
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];
}

-(void)setComment:(CommentModel *)comment {
    _comment = comment;
    
    NSString *content = [comment.content stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    
    self.commentLabel.text = content;
    self.usernameLabel.text = comment.user.username;
    
    NSString *title = [content stringByReplacingOccurrencesOfString:@" " withString:@"#"];
    CGRect textViewRect = [title
                           boundingRectWithSize:CGSizeMake(self.frame.size.width, CGFLOAT_MAX)
                           options:NSStringDrawingUsesLineFragmentOrigin
                           attributes:@{ NSFontAttributeName : self.commentLabel.font }
                           context:nil];
    self.commentHeightConstraint.constant = textViewRect.size.height;
    self.tableViewResponses.delegate = self;
    self.tableViewResponses.dataSource = self;
    

    self.tableViewResponses.estimatedRowHeight = 2000.0;
    self.tableViewResponses.rowHeight = UITableViewAutomaticDimension;
    
    
    [self.tableViewResponses reloadData];
    
    [self.avatarImageView setImageWithURL:[NSURL URLWithString:comment.user.avatarUrl]];
    
    [self.tableViewResponses layoutIfNeeded];
    self.constraintHeightTableView.constant = self.tableViewResponses.contentSize.height + self.tableViewResponses.contentInset.bottom+self.tableViewResponses.contentInset.top;
}

+ (CGFloat)getHeightFromTitle:(NSString *)comment andComments:(NSArray<CommentModel>*)comments andWith:(CGFloat)width {
    CGFloat totalHeight = 0;
    
    UIFont *usedFont = [UIFont fontWithName:@"AvenirNextCondensed-Regular" size:18];
    
    NSString *commentContent = [comment stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    NSString *title = [commentContent stringByReplacingOccurrencesOfString:@" " withString:@"#"];
    CGRect textViewRect = [title
                           boundingRectWithSize:CGSizeMake(width-109, CGFLOAT_MAX)
                           options:NSStringDrawingUsesLineFragmentOrigin
                           attributes:@{ NSFontAttributeName : usedFont }
                           context:nil];
    
    totalHeight = textViewRect.size.height+15;
    
    for (CommentModel *com in comments) {
        NSString *answerContent = [com.content stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        NSString *title = [answerContent stringByReplacingOccurrencesOfString:@" " withString:@"#"];
        CGRect textViewRect = [title
                               boundingRectWithSize:CGSizeMake(width - 173, CGFLOAT_MAX)
                               options:NSStringDrawingUsesLineFragmentOrigin
                               attributes:@{ NSFontAttributeName : usedFont }
                               context:nil];
        
        int height = textViewRect.size.height + kTableViewCellAnnexesHeight + 90;
        
        totalHeight += height;
    }
    
    return  totalHeight;
}

#pragma mark - TableView delegate/datasource methods

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.comment.answers.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    [self.tableViewResponses registerNib:[UINib nibWithNibName:NSStringFromClass([ResponseTableViewCell class]) bundle:nil]forCellReuseIdentifier:NSStringFromClass([ResponseTableViewCell class])];
    ResponseTableViewCell *cell = [self.tableViewResponses dequeueReusableCellWithIdentifier:@"ResponseTableViewCell"];
    
    CommentModel *comment = [self.comment.answers objectAtIndex:indexPath.row];
    cell.comment = comment;
    
    return cell;
}

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    return UITableViewAutomaticDimension;
}

ResponseTableViewCell.m

- (void)awakeFromNib {
    [super awakeFromNib];
    
    self.avatarImageView.layer.cornerRadius = self.avatarImageView.layer.frame.size.width / 2;
    self.avatarImageView.layer.masksToBounds = YES;
}

-(void)setComment:(CommentModel *)comment {
    _comment = comment;
    
    NSString *commentContent = [comment.content stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    self.commentLabel.text = commentContent;
    self.usernameLabel.text = comment.user.username;

    self.commentHeightConstraint.active = false;
    
    [self.avatarImageView setImageWithURL:[NSURL URLWithString:comment.user.avatarUrl]];
}

PS: Je sais qu'un tableView dans une cell est pas recommandé mais j'ai pas eu d'autres choix.

 

Merci à ceux qui m'aideront :)

Fichier(s) joint(s)



#2 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 996 messages
  • LocationPlestin-les-Grèves (22)

Posté 03 août 2017 - 17:49

De mon avis, il ne faut pas utiliser une deuxième tableView.

 

Vaut mieux d'avoir (au moins) deux type de cellules dans une tableView. En fait, ça pourrait être difficile, voire presque impossible.

 

N'oublies pas qu'il faut considérer comment gérer le développement et l'écroulement des conversations.



#3 Ben77650

Ben77650

    Torréfacteur de fèves

  • Membre
  • PipPipPipPipPip
  • 515 messages
  • LocationParis

Posté 03 août 2017 - 19:06

J'étais sur que quelqu'un dirait ça.

On a pas vraiment le choix, et une 2e cellule, ça ne rends pas comme le client aimerait...

Et de toute facebook utilise bien des tableaux dans ses cellules de tableau non ?



#4 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 996 messages
  • LocationPlestin-les-Grèves (22)

Posté 03 août 2017 - 19:21

J'étais sur que quelqu'un dirait ça.

 

Donc tu n'es pas déçu  >:D

 

On a pas vraiment le choix, et une 2e cellule, ça ne rends pas comme le client aimerait...

 

 

On a toujours le choix, même s'il faut dessiner par main sur une UIScrollView  :-*

 

Et de toute facebook utilise bien des tableaux dans ses cellules de tableau non ?

 

 

Bah non ! Je viens de voir sur mon portable et là je vois que, apparement, il utilise une tableView pour le premier "niveau" de la conversation puis il faut cliquer sur (n) commentaires pour voir la reste des commentaires ; ce qui affiche un deuxième viewController qui contient une tableView, dédié à afficher les commentaires, à part du premier viewController.

 

En aucun cas, je ne vois pas une tableView dans une cellule



#5 Ben77650

Ben77650

    Torréfacteur de fèves

  • Membre
  • PipPipPipPipPip
  • 515 messages
  • LocationParis

Posté 03 août 2017 - 19:24

Ce que tu viens de décrire de Facebook c'est exactement ce que j'ai.

Et moi je vois un commentaire dans une cellule d'un 1er tableView, et dans cette cellule un bouton, et un 2e tableView.

 

Et vu les deadlines non je n'avais pas le choix et le lead m'a aiguillé la dessus...



#6 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 996 messages
  • LocationPlestin-les-Grèves (22)

Posté 03 août 2017 - 19:38

Et moi je vois un commentaire dans une cellule d'un 1er tableView, et dans cette cellule un bouton, et un 2e tableView.

 

Encore bah non ! Ça pourrait être une UIStackView, ce qui est tout autre chose qu'une UITableView. N'importe comment les "segments" sont fait, il n'y a qu'un segment avec un commentaire et le bouton pour afficher le reste dans une tableView à part.

 

Et, avec la UIStackView avec un seul segment pour le premier commentaire, on n'aura pas les mêmes difficultés qu'avec une UITableView avec l'intégralité de la conversation.

 

Et vu les deadlines non je n'avais pas le choix et le lead m'a aiguillé la dessus...

 

 

Tu dis que l'on n'as pas discuté comment le faire avant d'arriver à un deadline imminent ?

 

Et, en plus, ton lead fait les suppositions en ne savant pas vraiment ce que Facebook a fait. Il y a plusieurs alternatives que l'on puisse choisir.



#7 Ben77650

Ben77650

    Torréfacteur de fèves

  • Membre
  • PipPipPipPipPip
  • 515 messages
  • LocationParis

Posté 03 août 2017 - 19:44

Je dis juste qu'on nous as dit il faut une v2 ça doit intégrer ça entre autres, et ça doit être fini pour la fin de semaine voila ^^



#8 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 996 messages
  • LocationPlestin-les-Grèves (22)

Posté 03 août 2017 - 19:59

Bien. Évidemment, tu as déjà décidé comment le faire ; pourquoi tu es venu ici pour demander ?

 

Ou, peut-être, c'est parce que tu ne peux pas arriver à le faire ? Et il ne reste qu'un jour pour trouver la solution ?

 

Si ton lead est convaincu que la deuxième tableView est possible avant demain, il faut lui dire de trouver comment le faire lui-même.

 

Sinon, il faut considérer les autres solutions. Tu n'acceptes pas l'idée d'une UIStackView ; peut-être tu devrais considérer, à la place d'une cellule par conversation, d'utiliser une section pour chaque conversation avec une cellule pour chaque commentaire là dedans.



#9 Draken

Draken

    Mouleur de chocolats

  • Artisan chocolatier
  • PipPipPipPipPipPipPipPip
  • 8 793 messages
  • LocationParis

Posté 03 août 2017 - 19:59

Loi 1 - Le patron a toujours raison

Loi 2 - Si le patron a tort, se référer à la loi 1


Garçon, servez-moi un Covfefe avec du lait de soja, sans OGM ..

Et faites régler la climatisation, il fait bien chaud, ici !

 

 

Éternel Novice !  :baby:

Tueur de poneys !  :(

 

Faire simple .. c'est compliqué !

Faire compliqué .. c'est simple !

 

Un MOOC (cours en ligne - dont je ne suis pas l'auteur) gratuit sur la programmation en Obj-C et en Swift 3, démarrant le 14 Mars 2017 :

https://www.edx.org/...onnex-progios1x

 

Des dizaines d'heures de tutoriels vidéo en français (je ne suis pas l'auteur) pour apprendre à développer en Obj-C et Swift : http://pagesperso-sy...don/5I452-2014/

 

 


#10 Ben77650

Ben77650

    Torréfacteur de fèves

  • Membre
  • PipPipPipPipPip
  • 515 messages
  • LocationParis

Posté 03 août 2017 - 20:02

Bien. Évidemment, tu as déjà décidé comment le faire ; pourquoi tu es venu ici pour demander ?

 

Ou, peut-être, c'est parce que tu ne peux pas arriver à le faire ? Et il ne reste qu'un jour pour trouver la solution ?

 

Si ton lead est convaincu que la deuxième tableView est possible avant demain, il faut lui dire de trouver comment le faire lui-même.

 

Sinon, il faut considérer les autres solutions. Tu n'acceptes pas l'idée d'une UIStackView ; peut-être tu devrais considérer, à la place d'une cellule par conversation, d'utiliser une section pour chaque conversation avec une cellule pour chaque commentaire là dedans.

 

Le lead est convaincu de cela, sauf qu'il y a 2 ou 3 projets à terminer pour demain (fermeture de l'entreprise pour vacances, donc de grosses deadlines).

 

Et oui ma deadline est pour demain, et je me sens mal de tout refaire et tout finir d'ici demain soir, pour ça que j'essaye de faire marcher ma solution actuelle (qui n'est pas la plus pertinente j'en conviens).



#11 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 996 messages
  • LocationPlestin-les-Grèves (22)

Posté 03 août 2017 - 20:06

Occupes-toi sur la solution d'utiliser un section pour chaque conversation, avec une cellule pour chaque commentaire.

 

Ça c'est faisable assez vite et c'est garantie de marcher  8--)

 

https://stackoverflo...itableview-cell



#12 Ben77650

Ben77650

    Torréfacteur de fèves

  • Membre
  • PipPipPipPipPip
  • 515 messages
  • LocationParis

Posté 03 août 2017 - 20:08

Mais avec ce système ça aura pas un look a la Facebook, si ? ^^



#13 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 996 messages
  • LocationPlestin-les-Grèves (22)

Posté 03 août 2017 - 20:11

Mais si !

 

Regardes les lignes entre les conversations ; elles sont assez épaisses et grises. Ceux sont les "headers" des sections.



#14 Ben77650

Ben77650

    Torréfacteur de fèves

  • Membre
  • PipPipPipPipPip
  • 515 messages
  • LocationParis

Posté 03 août 2017 - 20:13

Oki je regarderais ça demain alors, merci ;)



#15 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 996 messages
  • LocationPlestin-les-Grèves (22)

Posté 03 août 2017 - 20:16

Oh, et, après les vacances, tu devrais changer au moins une partie de ton code en remplaçant les multiples if…else avec un switch :

    switch comment.answers.count
    {
      case 0:

        cell.responseView.hidden = true;
        
        break;
      
      case 1:

        titleButton = [NSString stringWithFormat:NSLocalizedString(@"%ld answer", @""), [comment.answers count]];
        break;
      
      default:
        
        titleButton = [NSString stringWithFormat:NSLocalizedString(@"%ld answers", @""), [comment.answers count]];
        break;
    }

::)  8--)  :bravo!:



#16 Ben77650

Ben77650

    Torréfacteur de fèves

  • Membre
  • PipPipPipPipPip
  • 515 messages
  • LocationParis

Posté 03 août 2017 - 20:19

Après les vacances le projet sera surement livré donc bon ^^

 

Et puis bon c'est pas comme si celui qui avais fait la V1 m'avais laissé un projet dégueulasse x)



#17 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 996 messages
  • LocationPlestin-les-Grèves (22)

Posté 03 août 2017 - 20:28

Encore un projet livré avec le mauvais code qui cache les bogues en attendant les retours négatifs des utilisateurs.

 

Et, sans doute, on ne l'a pas testé rigoureusement car on n'a pas eu le temps  >:(

 

Dis-moi, c'est quelle entreprise ; afin que je puisse éviter d'acheter leurs produits ou, pire, de travailler là  :-*

 

Quand-même, pour toi, sur la localisation des quantités comme "1 answer", "n answers", lis cet article pendant les vacances  :-*

 

http://crunchybagel....os-development/



#18 Ben77650

Ben77650

    Torréfacteur de fèves

  • Membre
  • PipPipPipPipPip
  • 515 messages
  • LocationParis

Posté 03 août 2017 - 20:31

Si tu voyais l'état de la V1 c'est à en pleurer.

Et si ça a été testé quand même ;)

 

Et concernant la société je me garde le nom, juste c'est une agence mobile, qui développe des projets pour un de ses clients, et je ne crois pas une seule seconde que le produit que je développe va marcher (trop de concurrence) et concernant ma société actuelle c'est mon dernier jour chez eux demain (gestion de projet chaotique, j'ai décidé de partir).

Je regarderais malgré tout ton article merci à toi :)



#19 Joanna Carter

Joanna Carter

    Broyeur de fèves

  • Contrôleur d'arômes
  • 1 996 messages
  • LocationPlestin-les-Grèves (22)

Posté 03 août 2017 - 20:35

Dans ce cas là, bonnes vacances et bonne continuation pour le prochain contrat  :bravo!:






0 utilisateur(s) li(sen)t ce sujet

0 membre(s), 0 invité(s), 0 utilisateur(s) anonyme(s)