iOS直播间聊天室—图文混排加载网络图片(含Demo)

Question:

1.刷新直播间消息机制该用哪种方法?哪一种更加合适?

2.聊天室该如何图文混排?

3.聊天室出现特殊字符临界点不换行?高度计算错误?

4.聊天室该如何加载网络图片?

5.聊天室如何优化?

6.交互时刷新消息经常出现越界情况,导致崩溃?

7.聊天室出现阿拉伯文&中文&数字&英文等类似情况如何处理?

...

以上这些问题我相信做过聊天室直播间的肯定或多或少遇到过,那么本编文章就为了解决这些问题而来,底部提供Demo⬇️。

1.刷新直播间消息机制该用哪种方法?哪一种更加合适?

聊天室刷新分为两种:
一:采用来一条消息刷新一条消息,适用于小主播和人气较少的直播间。优点就是可以快速的查看到发言记录,给人丝滑流畅感,缺点就是刷新过于频繁,消耗性能。


image.png
直接刷新.gif

二:定时刷新,适用于大主播或某段活动时间内用户发言特别频繁时间段,假设一秒钟接收到几十条消息时你直接一条条刷新是毫无意义的,不仅影响性能而且用户也看不清。所以这种情况可以选择弄个定时器,每0.5秒刷新一次。至于多久刷新一次,你可以根据主播人气,观看人数,发言速度来调整。


image.png
0.5秒刷新一次.gif

通过对比,二者都是每秒接收到30条消息时,一条条刷新和定时刷新所消耗的性能非常明显。
如何选择,各位自行斟酌。

2.聊天室该如何图文混排?

如果在子线程生成我们的富文本,这个时候你肯定不可以在子线程创建UIimageView这些,然后转UIimage,我个人有几个技巧:
一:聊天肯定会带有等级系列,拿我的直播来说,现在有0-100级,我个人写了一个等级生成器,通过业务生成每个等级段所对应文字+图片+等级+渐变色形成view,然后我们启动APP时,通过view转image,内存就会保存有0-100张图片,所占300k左右而已。那么下次用的时候,直接传入等级获取对应的UIimage。

+ (instancetype)sharedInstance {
    static EWLevelManager *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[EWLevelManager alloc] init];
        instance.data = [NSMutableDictionary dictionary];
    });
    return instance;
}

- (void)setup {
    [self.data removeAllObjects];
    
    for (NSInteger i = 0; i <= 100; i++) {
        // NDLeveBgView就是我的等级生成器,返回view
        // 启动app我们调用一次这个方法,然后内存就有生成0-100等级图片
        NDLeveBgView *view = [[NDLeveBgView alloc] init];
        view.frame = CGRectMake(0, 0, 30.0, 14.0);
        view.layer.cornerRadius = 2;
        view.layer.masksToBounds = YES;
        view.isShadeLv = YES;
        view.level = i;
        
        [self.data setObject:[self convertCreateImageWithUIView:view] forKey:[NSString stringWithFormat:@"%li", (long)i]];
    }
    
//    NSMutableData *data = [[NSMutableData alloc]init];
//    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
//    [archiver encodeObject:self.data forKey:@"talkData"];
//    [archiver finishEncoding];
//    NSLog(@"查看byte = %lu", (unsigned long)data.length);
}

- (UIImage *)imageForLevel:(NSInteger)Level {
    return [self.data objectForKey:[NSString stringWithFormat:@"%li", (long)Level]];
}


/** 将 UIView 转换成 UIImage */
- (UIImage *)convertCreateImageWithUIView:(UIView *)view {
    
    //UIGraphicsBeginImageContext(view.bounds.size);
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, [UIScreen mainScreen].scale);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [view.layer renderInContext:ctx];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return newImage;
}

至于图片如何转富文本我就不多赘述了,这种没啥可说的,都在demo中。

3.聊天室出现特殊字符临界点不换行?高度计算错误?

我想肯定有人遇到过这个问题,当我们使用UILabel时,根据消息生成的富文本,高度计算得明明很正确,但就是不换行!!当我们在测试的时候明明运行一切都正常,但是到了线上就出现不换行,高度计算错误等等系列问题。

我可以很明确的告诉大家,这就是UILabel的问题,他在不同系统版本表现不一样,经过我多次测试,曾经一度让我怀疑是不是我的问题,但是后来我换了YYLabel后,一切都清净了,所以抛弃UILabel吧,它在表达复杂的文本时,总是不那么如意。
跟我说一句:YYKit牛逼🐂!!!

可能有同学反驳,其实我也想证明是我的问题,如果有同学用UILabel做的直播间聊天室,希望不吝赐教。

4.聊天室该如何加载网络图片?

这个问题其实也好解决。
当我们生成礼物消息富文本时,先用礼物缩略的占位图替代,同时使用SD下载该图片,下载完了以后重新生成该富文本,接着通过代理回调去刷新该cell。

case NDSubMsgType_Gift_Text: {   // 礼物弹幕(文本)消息
            // 下载标签图片
            [self downloadTagImage];
            // 下载礼物图片
            [self downloadGiftImage];
            self.bgColor = NormalBgColor;
            [self Gift_Text];
        }
            break;

/** 下载礼物缩略图 */
- (void)downloadGiftImage {
    NSString *urlStr = self.msgModel.giftModel.thumbnailUrl;
    if (!urlStr || urlStr.length < 1) {
        return;
    }
    if (self.finishDownloadGiftImg) {
        return;
    }
    self.finishDownloadGiftImg = YES;
    
    // 1. 如果本地有图片
    self.giftImage = [self cacheImage:urlStr];
    if (self.giftImage) {
        return;
    }
    
    // 2. 下载远程图片
    NSURL *url = [NSURL URLWithString:urlStr];
    EWWeakSelf
    id sdLoad = [[SDWebImageManager sharedManager] loadImageWithURL:url options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
        
    } completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
        if (image){
            // 刷新UI
            weakSelf.giftImage = image;
            // 更新属性文字
            [weakSelf downloadTagImageFinish];
        }
    }];
    [self.tempLoads addObject:sdLoad];
}

- (void)downloadTagImageFinish {
    // 更新属性文字
    [self msgUpdateAttribute];
    // 通知代理刷新属性文字
    if (self.delegate && [self.delegate respondsToSelector:@selector(attributeUpdated:)]) {
        [self.delegate attributeUpdated:self];
    }
}

/** 消息属性文字发生变化(更新对应cell) */
- (void)msgAttrbuiteUpdated:(NDMsgModel *)msgModel {
    NSInteger row = [self.msgArray indexOfObject:msgModel];
    if (row >= 0) {
        [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:row inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
        if (row == self.msgArray.count - 1) {
            [self scrollToBottom:YES];
        }
    }
}

以上代码都是关键部分,更详细可以对照demo。

5.聊天室如何优化?

聊天室的优化其实也就是UITableView的优化:

一:我们所有的cell通过复用,每一种消息类型对应不同cell。


image.png

二:所有的消息所需要的背景颜色,富文本,高度等等都用模型记录。


image.png

三:cell高度缓存,每次都从我们的模型读取,更加高效快捷。

6.交互时刷新消息经常出现越界情况,导致崩溃?

崩溃的原因大多数都在同时对同一个数组操作、插入indexPaths出现问题等。
一:如何保证同一时间数组只执行一种操作?
加锁
锁有好多种,有自旋锁、信号量、递归锁、互斥锁等等
自旋锁性能最高,但是经过苹果确认是有问题存在的,所以你可以选择其他类型。
这里我选择的是互斥锁:

#pragma mark - 消息追加
- (void)addNewMsg:(NDMsgModel *)msgModel {
    if (!msgModel) return;
    
    pthread_mutex_lock(&_mutex);
    // 消息不直接加入到数据源
    [self.tempMsgArray addObject:msgModel];
    pthread_mutex_unlock(&_mutex);
    
    if (_reloadType == NDReloadLiveMsgRoom_Direct) {
        [self tryToappendAndScrollToBottom];
    }
}

/** 追加数据源 */
- (void)appendAndScrollToBottom {
    if (self.tempMsgArray.count < 1) {
        return;
    }
    pthread_mutex_lock(&_mutex);
    // 执行插入
    .....代码块
    
    pthread_mutex_unlock(&_mutex);
    
   ...代码块

//清空消息重置
- (void)reset {
    pthread_mutex_lock(&_mutex);
    
    ...代码块
    pthread_mutex_unlock(&_mutex);
}
}

更多详见demo。

二:插入indexPaths出现越界问题,其实这个问题的产生也是因为我们对数组同时操作而导致的,如果你解决了数组的问题,那么这个问题也迎刃而解。

7.聊天室出现阿拉伯文&中文&数字&英文等类似情况如何处理?

这个问题非常有意思!具体可参考这篇文章
因为阿拉伯文、希腊文等系列语言是强语言,并且从右向左排列,而我们的中文也属于强语言,但是从左向右排列。当这二者碰撞到一起会怎么样呢?
到底是遵从我们的规则还是遵从阿拉伯文的规则?

我这里做的是强制按照中文规则排版。

// 强制排版(从左到右)
    attribute.yy_baseWritingDirection = NSWritingDirectionLeftToRight;
    attribute.yy_writingDirection = @[@(NSWritingDirectionLeftToRight | NSWritingDirectionOverride)];

// 强制排版(从左到右)
    paraStyle.alignment = NSTextAlignmentLeft;
    paraStyle.baseWritingDirection = NSWritingDirectionLeftToRight;

如果大家觉得有什么问题的,可以评论指出。

最后就是我们的demo了,如果觉得可以的希望点个star哦,Github

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 期待了两个星期的“好吗好的”民谣音乐会终于如期举行。在这期间我的心情为:期待—失落—重燃希望—欣喜同时又有点愧疚。...
    瑶小瑶18阅读 231评论 0 2
  • 我把阳光存起来 寄给有需要的人 我把生命存起来 寄给有需要的人 我把幸福存起来 寄给有需要的人 我把善良存起来 寄...
    英雄拒绝黄昏阅读 246评论 0 3
  • 月光倾泻,清凉如水。披上一件外衣足以抵挡这凛冽。时光前进后退,透明玻璃的裂痕寸寸入我心。我在等什么?伸出手游丝般的...
    是咕咚哦阅读 196评论 0 0