iOS 实现优酷视频的评论回复功能

一、概述

通过学习前面笔者提供的两种方法来实现类似微信朋友圈的评论回复功能后,首先,笔者来分析两者两者的优缺点,以及两者的使用场景。其次,笔者将通过方式一即用段头+Cell+段尾 的方法来实战优酷视频的评论回复功能,主要分析里面的业务逻辑数据处理以及细节处理。最后,希望能为广大开发者提供一点思路,少走一些弯路,填补一些细坑。

  • 方式一:使用段头+Cell+段尾推荐使用

    • 优点:评论回复cell(MHCommentCell)发挥出了UITableViewCell的重用机制;评论回复cell(MHCommentCell)的事件传递相比方式二少了一层嵌套;ModelFrame的计算针对性强。
    • 缺点:要实现tableView代理的- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section以及- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section方法,以及设置对应的高度,代码上略微繁琐。
    • 使用场景:支持无限评论回复的情况下。
  • 方式二:使用UITableViewCell嵌套UITableView

    • 优点:控制器的代码相比方式一的简单。
    • 缺点:外层的UITableView发挥了重用机制,但是Cell嵌套的UITableView未发挥重用机制,如果有1000条评论回复,那么嵌套的UITableViewCell(MHCommentCell)就得创建1000次,相当不合理,性能不好;ModelFrame的计算稍微复杂,实现的计算好内层嵌套的tableView的尺寸;评论回复cell(MHCommentCell)的事件传递,存在两层代理嵌套。
    • 使用场景:显示评论回复有限的情况下。
  • 传送门

二、效果图
youkuComment.gif
三、页面分析
  1. 效果图
MHYouKuControllers.jpg
  1. 图中字符对应的Controller
    A:MHYouKuController
    B:MHYouKuTopicController (红色框区域)
    C:MHYouKuTopicDetailController
    D:MHYouKuCommentController
    注意:文章统一用字符代替对应的Controller,怪我懒,望体谅。

  2. 评论面板(MHYouKuInputPanelView

MHYouKuInputPanelView@2x.png
四、需求分析
  1. A控制器和B控制器的的评论数据来源问题。
    首先,A控制器和B控制器存在父子关系,即:[A addChildViewController:B] ,具体使用细节请参考文末的Demo链接。其次,A控制器里面的tableView无法支持下拉刷新上拉加载功能,B控制器里面的tableView支持的,这种需求在视频类App非常常见,A控制器只是显示部分评论数据,点击评论数按钮跳转到B控制器来显示更多评论数据数据。终上所述,笔者采取的是在B控制器里面一旦下拉刷新获取数据后,通过代理或者通知,将评论数据回调给A控制器处理即可(PS:笔者在此采用的通知:MHCommentRequestDataSuccessNotification)。

    数据来源@2x.png

  2. 评论Cell显示查看全部xx条回复的实现问题。
    笔者这里采取了一种巧妙的方式,配置一个前端事先制定的MHComment即可。详细配置如下

    /** topic --- topicFrame */
    - (MHTopicFrame *)_topicFrameWithTopic:(MHTopic *)topic
    {
        // 这里要判断评论个数大于2 显示全部评论数
        if (topic.commentsCount>2) {
        // 设置假数据
        MHComment *comment = [[MHComment alloc] init];
        // MHAllCommentsId是前端设定的
        comment.commentId = MHAllCommentsId;
        comment.text = [NSString stringWithFormat:@"查看全部%zd条回复" , topic.commentsCount];
        // 添加假数据
        [topic.comments addObject:comment];
    }
    
        MHTopicFrame *topicFrame = [[MHTopicFrame alloc] init];
        // 传递话题模型数据,计算所有子控件的frame
        topicFrame.topic = topic;
        return topicFrame;
    }
    
  3. D控制器对视频,评论成功后,A控制器和B控制器的数据同步问题(即:两者在评论数据上保持一致,从而保证在界面上显示一致)。
    点击A控制器和B控制器的评论框,即可跳转到D控制器,即D控制器是一对多的关系。若D控制器对视频评论成功后,笔者通过通知(通知名字:MHCommentSuccessNotification)的方式,来告知AB控制器作相应的操作即可。

    视频评论@2x.png

  4. 若对AB以及C控制器里面的某个视频评论进行回复或者针对某条视频评论的回复进行评论,如何保证A控制器和B控制器的数据同步问题(即:两者在评论数据上保持一致,从而保证在界面上显示一致)。
    关键:AB以及C控制器持有的是同一个模型(MHTopicFrame),这样我们无论对数据做了任何操作,只要监听到改变时,刷新数据源方法即可。

    评论Or回复@2x.png

  5. 视频评论和回复成功后的数据处理问题。
    由于查看全部xx条回复是前端自己配置,伴随着视频的评论Or回复成功后,数据需要做相应的判断(MHYouKuInputPanelViewDelegate)。

    - (void) inputPanelView:(MHYouKuInputPanelView *)inputPanelView attributedText:(NSString *)attributedText
    {
         // 发送评论 模拟网络发送
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.25f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            // 评论或者回复成功
            MHComment *comment = [[MHComment alloc] init];
            comment.mediabase_id = self.mediabase_id;
            comment.commentId = [NSString stringWithFormat:@"%zd",[NSObject mh_randomNumber:0 to:100]];
            comment.text = attributedText;
            comment.creatTime = [NSDate mh_currentTimestamp];
        
            MHUser *fromUser = [[MHUser alloc] init];
            fromUser.userId = [AppDelegate sharedDelegate].account.userId ;
            fromUser.avatarUrl = [AppDelegate sharedDelegate].account.avatarUrl;
            fromUser.nickname = [AppDelegate sharedDelegate].account.nickname;
            comment.fromUser = fromUser;
            // 只有回复  toUser 有值
            if (inputPanelView.commentReply.isReply) {
                MHUser *toUser = [[MHUser alloc] init];
                toUser.avatarUrl = inputPanelView.commentReply.user.avatarUrl;
                toUser.userId = inputPanelView.commentReply.user.userId;
                toUser.nickname = inputPanelView.commentReply.user.nickname;
                comment.toUser = toUser;
            }
            // 这里需要插入假数据 提高用户的体验度
            MHCommentFrame* newCommentFrame = [[MHTopicManager sharedManager] commentFramesWithComments:@[comment]].lastObject;
            // 这里要插入话题数据源中去
            // 修改评论回复数目
            self.selectedTopicFrame.topic.commentsCount  =  self.selectedTopicFrame.topic.commentsCount + 1;
            // 判断数据
            if (self.selectedTopicFrame.topic.comments.count>2) 
                // 有查看全部xx条回复 
                // 插入数据
                NSInteger count = self.selectedTopicFrame.commentFrames.count;
                NSInteger index = count - 1;
                [self.selectedTopicFrame.commentFrames insertObject:newCommentFrame atIndex:index];
                [self.selectedTopicFrame.topic.comments insertObject:comment atIndex:index];
    
                // 取出最后一条数据 就是查看全部xx条回复 修改为xx+1条即可
                MHComment *lastComment = self.selectedTopicFrame.topic.comments.lastObject;
                lastComment.text = [NSString stringWithFormat:@"查看全部%zd条回复" , self.selectedTopicFrame.topic.commentsCount];
             }else if (self.selectedTopicFrame.topic.comments.count == 2) {
                    // 添加数据源
                    [self.selectedTopicFrame.commentFrames addObject:newCommentFrame];
                    [self.selectedTopicFrame.topic.comments addObject:comment];
                
                    // 设置假数据
                    MHComment *lastComment = [[MHComment alloc] init];
                    lastComment.commentId = MHAllCommentsId;
                    lastComment.text = [NSString stringWithFormat:@"查看全部%zd条回复" , self.selectedTopicFrame.topic.commentsCount];
                    MHCommentFrame *lastCommentFrame =  [[MHTopicManager sharedManager] commentFramesWithComments:@[lastComment]].lastObject;
                    // 添加假数据
                    [self.selectedTopicFrame.commentFrames addObject:lastCommentFrame];
                    [self.selectedTopicFrame.topic.comments addObject:lastComment];
                }else{
                    // <2的情况 直接添加即可 
                    // 添加数据源
                    [self.selectedTopicFrame.commentFrames addObject:newCommentFrame];
                    [self.selectedTopicFrame.topic.comments addObject:comment];
                }
            // 发送评论回复成功的通知
            [MHNotificationCenter postNotificationName:MHCommentReplySuccessNotification object:nil userInfo:@{MHCommentReplySuccessKey:self.selectedTopicFrame}]; 
        };
    }
    
五、期待
  1. 文章若对您有点帮助,请给个喜欢❤️,毕竟码字不易;若对您没啥帮助,请给点建议💗,切记学无止境。
  2. 针对文章所述内容,阅读期间任何疑问;请在文章底部评论指出,我会火速解决和修正问题。
  3. GitHub地址:https://github.com/CoderMikeHe
六、代码

MHDevelopExample_Objective_C - MHYouKuController.h/m

推荐阅读更多精彩内容