项目实战No10 评论管理

本文介绍了一款iOS应用中评论区的UI设计及交互实现细节,包括自定义TableViewCell、键盘管理、评论数据展示等,并提供了代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 视频帖子

  • 初始化
- (void)setTopic:(XMGTopic *)topic
{
    _topic = topic;

    [self.imageView sd_setImageWithURL:[NSURL URLWithString:topic.image1]];
    self.playCountLabel.text = [NSString stringWithFormat:@"%zd播放", topic.playcount];

    NSInteger minute = topic.videotime / 60;
    NSInteger second = topic.videotime % 60;
    // %02zd :显示这个数字需要占据2位空间,不足的空间用0替补
    self.videoTimeLabel.text = [NSString stringWithFormat:@"%02zd:%02zd", minute, second];
}

二 属性名-字典key映射(key-mapping)

  • 服务器返回字段不容易读,我们自定义属性,用第三方框架把大写ID换成服务器返回的id
+ (NSDictionary *)replacedKeyFromPropertyName
{
    return @{
             @"ID" : @"id",
             @"small_image" : @"image0",
             @"middle_image" : @"image2",
     @"profile_image" : @"other.test[0]"   // 数组关系 
     @"name" : @"data.info.name"       // 多层级属性映射 
// 依次将数组中每个key对应的值赋值给模型的name属性,直到name属性真正有值为止
           @"name" : @[@"fgdgfdg", @"image0", @"name"]
             };
}
  • 把所有属性名转成下划线的key
 return [propertyName underlineFromCamel];
  • 数组中装什么模型
+ (NSDictionary *)objectClassInArray
{
    // 数组名 : 模型名
    return @{@"top_cmt" : [XMGComment class]};
    //  担心写错,还有另一种写法
    return @{@"top_cmt" : @"XMGComment"};
}

三 最热评论

  • 最新评论
    • 有最新评论时cellheight需添加高度
  if (self.topComment) {
       NSString *username = self.topComment.user.username;
       NSString *content = self.topComment.content;
       NSString *cmtText = [NSString stringWithFormat:@"%@ : %@", username, content];
   // 评论内容的高度
        CGFloat cmtTextH = [cmtText boundingRectWithSize:CGSizeMake(textW, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:14]} context:nil].size.height;

     _cellHeight += XMGTopicTopCmtTopH + cmtTextH + XMGCommonMargin;
        }
     // 工具条的高度
     _cellHeight += XMGTopicToolbarH + XMGCommonMargin;
    } 
    return _cellHeight;
}

注意:文件不参与编译情况:文件被删了或不勾选Targets项

这里写图片描述

  • 按钮不能交互,点击事件传递给后面的imageView

    这里写图片描述

    • 评论控制器
- (void)viewDidLoad {
    [super viewDidLoad];

    self.title = @"评论";
    self.navigationItem.rightBarButtonItem = [UIBarButtonItem itemWithImage:@"comment_nav_item_share_icon" highImage:@"comment_nav_item_share_icon_click" target:nil action:nil];
    //  监听键盘
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
}
  • 工具条上移
#pragma mark - 监听
- (void)keyboardWillChangeFrame:(NSNotification *)note
{
    // 工具条平移的距离 == 屏幕高度 - 键盘最终的Y值
    self.bottomSpace.constant = XMGScreenH - [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y;

    CGFloat duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    [UIView animateWithDuration:duration animations:^{
        [self.view layoutIfNeeded];
    }];
}
  • 拖拽cell退出键盘
    • 遵守代理 UITableViewDelegate
#pragma mark - <UITableViewDelegate>
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.view endEditing:YES];
}

四 评论tableView实现

  • 给tableview设置数据源:有2种类型的cell
    • 方案1:有帖子类型cell和评论类型cell,2种类型cell
    • 方案2:有帖子类型cell、最新评论cell和最热评论cell,3种类型cell
#pragma mark - <UITableViewDataSource> 3组代码
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 3;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (section == 0) return 1;
    if (section == 1) return 10;
    return 5;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 0) { // 帖子cell
        return [tableView dequeueReusableCellWithIdentifier:@"topic"];
    } else { // 评论cell
        return [tableView dequeueReusableCellWithIdentifier:@"comment"];
    }
}
  • 注册cell
- (void)setupTable
{
    [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([XMGTopicCell class]) bundle:nil] forCellReuseIdentifier:@"topic"];
    [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([XMGCommentCell class]) bundle:nil] forCellReuseIdentifier:@"comment"];
}
  • 每组cell组头设置
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    if (section == 0) return nil;
    if (section == 1) return @"最热评论";
    return @"最新评论";
}
  • cell页头(header)设置
- (void)setupTable
{
    [self.tableView registerNib:[UINib nibWithNibName:NSStringFromClass([XMGCommentCell class]) bundle:nil] forCellReuseIdentifier:@"comment"];

    // 设置header
    XMGTopicCell *cell = [XMGTopicCell viewFromXib];
    cell.topic = self.topic;
    cell.frame = CGRectMake(0, 0, XMGScreenW, self.topic.cellHeight);
//    cell.width = XMGScreenW;
//    cell.height = self.topic.cellHeight;

    UIView *header = [[UIView alloc] init];
    header.height = cell.height + 2 * XMGCommonMargin;
    header.backgroundColor = [UIColor redColor];
    [header addSubview:cell];

    self.tableView.tableHeaderView = header;
}
  • 最热评论隐藏(点击帖子进去之后)
    • 清掉最热评论,评论为空,隐藏最新评论,重设置高度
- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];

    // 恢复帖子的最热评论数据
    if (self.topComment) {
    // 高度清0,重新设置高度
        self.topic.topComment = self.topComment;
        self.topic.cellHeight = 0;
    }
}
  • 评论数据
   // 最热评论
  weakSelf.hotComments = [XMGComment objectArrayWithKeyValuesArray:responseObject[@"hot"]];
  // 最新评论
  weakSelf.latestComments = [XMGComment objectArrayWithKeyValuesArray:responseObject[@"data"]];
  • cell样式代码
#pragma mark - <UITableViewDataSource>
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    if (self.hotComments.count) return 2;
    if (self.latestComments.count) return 1;
    return 0;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (section == 0 && self.hotComments.count) {
        return self.hotComments.count;
    }

    return self.latestComments.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    XMGCommentCell *cell = [tableView dequeueReusableCellWithIdentifier:XMGCommentCellId];

    // 获得对应的评论数据
    NSArray *comments = self.latestComments;
    if (indexPath.section == 0 && self.hotComments.count) {
        comments = self.hotComments;
    }
    // 传递模型给cell
    cell.comment = comments[indexPath.row];
    return cell;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    XMGCommentHeaderView *header = [tableView dequeueReusableHeaderFooterViewWithIdentifier:XMGHeaderId
                                           ];
    // 覆盖文字
    if (section == 0 && self.hotComments.count) { // 第0组且有最热评论
        header.text = @"最热评论";
    } else {
        header.text = @"最新评论";
    }
    return header;
}
  • 重写评论set方法
- (void)setComment:(XMGComment *)comment
{
    _comment = comment;

    if (comment.voiceuri.length) {
        self.voiceButton.hidden = NO;
        [self.voiceButton setTitle:[NSString stringWithFormat:@"%zd''", comment.voicetime] forState:UIControlStateNormal];
    } else {
        self.voiceButton.hidden = YES;
    }

    [self.profileImageView setHeader:comment.user.profile_image];
    self.contentLabel.text = comment.content;
    self.usernameLabel.text = comment.user.username;
    self.likeCountLabel.text = [NSString stringWithFormat:@"%zd", comment.like_count];
  // 判断男女图标
    if ([comment.user.sex isEqualToString:XMGUserSexMale]) {
        self.sexView.image = [UIImage imageNamed:@"Profile_manIcon"];
    } else {
        self.sexView.image = [UIImage imageNamed:@"Profile_woamanIcon"];
    }
}
  • 自动计算cell高度
// 需要设置估算高度
  self.tableView.estimatedRowHeight = 100;
  self.tableView.rowHeight = UITableViewAutomaticDimension;
  • 语音评论
    • 判断语音Button是否隐藏(直接判断comment有没有值,注意comment可能是nill,判断length不会有这情况)
if (comment.voiceuri.length) {
        self.voiceButton.hidden = NO;
        [self.voiceButton setTitle:[NSString stringWithFormat:@"%zd''", comment.voicetime] forState:UIControlStateNormal];
    } else {
        self.voiceButton.hidden = YES;
    }
  • 自定义cell头部样式
    • 由于label的x和y值没法调整,最好在包装一次UIView
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    // label
    UILabel *label = [[UILabel alloc] init];
    if (section == 0 && self.hotComments.count) {
        label.text = @"最热评论";
    } else {
        label.text = @"最新评论";
    }
    label.x = XMGCommonSmallMargin;
    [label sizeToFit];
    label.textColor = XMGGrayColor(120);
    label.font = [UIFont systemFontOfSize:14];

    // header
    UIView *header = [[UIView alloc] init];
    header.backgroundColor = self.tableView.backgroundColor;
    [header addSubview:label];

    return header;
}

苹果有个类专门做HeaderFooter,UITableViewHeaderFooterView

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    // label
    UILabel *label = nil;

    // header
    static NSString *ID = @"header";
    static NSInteger tag = 99;
    UITableViewHeaderFooterView *header = [tableView dequeueReusableHeaderFooterViewWithIdentifier:ID];
    if (header == nil) { // 缓存池中没有header
        header = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:ID];
        header.contentView.backgroundColor = self.tableView.backgroundColor;

        // label
        label = [[UILabel alloc] init];
        label.x = XMGCommonSmallMargin;
        label.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        label.textColor = XMGGrayColor(120);
        label.tag = tag;
        label.font = [UIFont systemFontOfSize:14];
        [header.contentView addSubview:label];
    } else { // 这个header是从缓存池中取出来(这个header里面本身就已经有label)
        label = (UILabel *)[header viewWithTag:tag];
    }

    // 覆盖文字
    if (section == 0 && self.hotComments.count) {
        label.text = @"最热评论";
    } else {
        label.text = @"最新评论";
    }
    return header;
}
  • 自定义
- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier
{
    if (self = [super initWithReuseIdentifier:reuseIdentifier]) {
        self.contentView.backgroundColor = XMGCommonBgColor;

        // label
        UILabel *label = [[UILabel alloc] init];
        label.x = XMGCommonSmallMargin;
        label.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        label.textColor = XMGGrayColor(120);
        label.font = [UIFont systemFontOfSize:14];
        [self.contentView addSubview:label];
        self.label = label;
    }
    return self;
}

- (void)setText:(NSString *)text
{
    _text = [text copy];

    self.label.text = text;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值