OC 在线直播五百人同时聊天时造成视频卡顿解决办法

Header_8.jpg

问题描述

观看直播情况下,直播间五百人同时发送消息,聊天界面展示会很耗性能,影响直播视频正常播放

分析和解决方案

1.聊天接收时,收到的代理方法会传递一个字典,这个字典包含这条聊天的所有信息,但是接收到这个消息后,我这边没有任何处理,直接把这个东西交给我的DataSourceManager去处理,然后将解析过的lastObject给chatView去添加cell。


屏幕快照 2019-03-08 上午10.54.50.png

这个时候就造成一个问题,如果一秒钟我这边接收到了100条消息,我这个流程就要走100次,然后在TableView中reload100次。

为了避免这个问题,可以在接收到这个消息后,进行一些处理,如果每秒钟发送多条消息,就将这些消息打包,然后交给chatView直接添加这个数组就可以了

屏幕快照 2019-03-08 上午11.07.04.png

下面是处理每秒钟加载过多消息进行的限制

//解析公聊消息
    WS(ws)
    [self.manager addPublicChat:dic userDic:self.userDic viewerId:self.viewerId groupId:self.groupId danMuBlock:^(NSString * _Nonnull msg) {
        //弹幕
        [ws.playerView insertDanmuString:msg];
    }];
    //判断时间
    NSString *publistTime = dic[@"time"];
    NSInteger publish = [NSString timeSwitchTimestamp:publistTime andFormatter:@"HH:mm:ss"];
    if (_lastTime == publish) {
        //添加数组
        [self.chatArr addObject:[self.manager.publicChatArray lastObject]];
//        NSLog(@"同一秒,添加至数组");
        [_updateTimer invalidate];
        WS(weakSelf)
        _updateTimer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:NO block:^(NSTimer * _Nonnull timer) {
            if (weakSelf.chatArr.count != 0) {
                [weakSelf.chatView addPublicChatArray:weakSelf.chatArr];
                [weakSelf.chatArr removeAllObjects];
//                NSLog(@"延迟数据校对");
            }
        }];
    }else{
        if (self.chatArr.count != 0) {
            [self.chatView addPublicChatArray:self.chatArr];
            [self.chatArr removeAllObjects];
//            NSLog(@"将数组中的元素添加至消息中");
        }
        [self.chatView addPublicChat:[self.manager.publicChatArray lastObject]];
        _lastTime = publish;
//        NSLog(@"+++++++++++++++++");
    }

到这里解决了一个问题,当每秒钟消息过多,让他只走了一遍reloadData
2.优化到这里后,iphone7及以上机型播放直播视频加五百人聊天已经不卡顿了,但是在iphone6 iphone6plus 还是有轻微卡顿,而且卡顿还是1S一卡顿,和我这个延迟机制刚好相对应
ChatView中处理添加数组方法

/**
 添加一个聊天数组(直播公聊如果每秒钟发送消息过多,会调用这个方法)

 @param array 聊天数组
 */
-(void)addPublicChatArray:(NSMutableArray *)array{
    if([array count] == 0) return;
    
    NSInteger preIndex = [self.publicChatArray count];
    [self.publicChatArray addObjectsFromArray:[array mutableCopy]];
    NSInteger bacIndex = [self.publicChatArray count];
    
    NSMutableArray *indexPaths = [[NSMutableArray alloc] init];
    for(NSInteger row = preIndex + 1;row <= bacIndex;row++) {
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:(row-1) inSection:0];
        [indexPaths addObject: indexPath];
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.publicTableView reloadData];
        //防止越界
        NSIndexPath *lastIndexPath = [indexPaths lastObject];
        if ((long)lastIndexPath.row > self.publicChatArray.count) {
            return;
        }
//        [self.publicTableView beginUpdates];
//        [self.publicTableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
//        [self.publicTableView endUpdates];
        if (indexPaths != nil && [indexPaths count] != 0 ) {
            [self.publicTableView scrollToRowAtIndexPath:[indexPaths lastObject] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
        }
    });
}

考虑到这个问题,也有可能是配置比较低的机型每秒钟加载数组过长,所以这里加了一个舍弃机制,这个数据过长的话就只加载最近的几条

//让每秒钟发送消息超过10条时,取最新的十条
    if (array.count > 10 && self.input == YES ) {
//        NSInteger count = array.count;
        NSRange range = NSMakeRange(0, array.count - 10);
        [array removeObjectsInRange:range];
//        NSLog(@"每秒钟数据%d个,加载最新10条, 目前消息数%lu", count, self.publicChatArray.count);
    }

3.优化了前面两个之后,有一个问题,我remove掉的那些数据是丢失了吗?如果我滑到顶部下拉刷新能不能查看之前的消息
下拉刷新机制

/**
 下拉刷新新数据
 */
-(void)loadNewData{
/* 
ChatViewDataSourceManager是一个数据处理中心单例,所有的消息要经过这个类去处理model,
并且这个数据中的聊天数组包含所有经过处理的聊天信息
*/
    if ([ChatViewDataSourceManager sharedManager].publicChatArray.count > self.publicChatArray.count) {
        NSMutableArray *arr = [ChatViewDataSourceManager sharedManager].publicChatArray;
        NSInteger selfCount = self.publicChatArray.count;
        NSInteger insertCount = arr.count - selfCount;
        insertCount = insertCount > 10 ? 10 : insertCount;//判断未展示的消息数据是否大于10条
        //加载10条数据
        for (NSInteger i = arr.count - selfCount; i > arr.count - selfCount - insertCount; i--) {
            [self.publicChatArray insertObject:arr[i] atIndex:0];
        }
//        NSLog(@"刷新了%d条数据,总条数%d, 目前条数%d", insertCount, arr.count, self.publicChatArray.count);
        [self.publicTableView reloadData];
        [self.publicTableView.mj_header endRefreshing];
    }else{
//        NSLog(@"没有更多数据了");
        [self.publicTableView.mj_header endRefreshing];
    }
}

避免tableView显示过多cell机制

 //当前cell数量大于60时,加载最新20条,下拉刷新从单例数组中取
    if (self.publicChatArray.count > 60) {
        NSRange range =NSMakeRange(0, self.publicChatArray.count - 20);
        [self.publicChatArray removeObjectsInRange:range];
//        NSLog(@"count大于60,返回最新20条,目前消息条数%lu", self.publicChatArray.count);
    }

总结

1.数据量过大时,延迟1S展示,通过数组打包交给ChatView渲染
2.舍弃机制,避免加载过多的cell,毕竟一个屏幕直播占一块,聊天占一块,没必要一次性加载100条,够两个屏幕的宽度就可以,然后通过下拉刷新去取数据就可以

tableView的其他坑

1.数据预处理

2.cell视图渲染

3.行高处理

4.异步获取聊天图片刷新

你可能感兴趣的:(OC 在线直播五百人同时聊天时造成视频卡顿解决办法)