iOS实现一个开源的IMKit

作者: 151ba12c22e5 | 来源:发表于2016-08-22 12:18 被阅读1286次

    用过融云IMKit的人想必都会吐槽一番,因为是闭源的项目,想要进行�复杂的定制着实要费一番功夫。虽然可以用IMLib自己实现UI,真的做起来也不免费些心思。现在Github上有很多�例如UUChat等优秀的IM框架,但是�也并不能很快的实现与IML�ib的对接。基于以上原因,这个框架便孕育而生。啰嗦了这么多,接下来的几篇文章将详细的讲一些这个项目用到的一些东西。

    首先,这个项目的布局完全基于Masonry,也就是对�AutoLayout的一层封装,把之前又臭又长的NSLayoutConstraint封装成链式语法,造福了我这种Storyboard黑粉。ok,接下来讲一下项目里用到了哪些Masonry的黑魔法

    气泡

    整个聊天的UI,�主要就是一个tableview,那��么问题来了,怎么能让�cell里的气泡可长可短可大可小呢,这里先普及个概念,intrinsicContentSize�这个属性存在于UIButton,UILabel,UITextView,UIImage�View等一切有‘内容’的控件,�比如说上图气泡中的UILabel,在绘制文字的时候会在内部调用CTFramesetterSuggestFrameSizeWithConstraints计算出一个size,这个size正是内容的size,这也就是调用sizeToFit后会‘自动’给Label一个size的原因。知道了这个神奇的属性,接下来我们就需要用Label的size去�‘撑开’这个气泡

    //添加气泡与cell的约束

    [self.bubbleImageViewmas_makeConstraints:^(MASConstraintMaker*make) {

    make.top.equalTo(self.avatarImageView.mas_top).offset(0);

    make.bottom.equalTo(self.contentView.mas_bottom).offset(-8);

    SMAS(make.left.equalTo(self.avatarImageView.mas_right).offset(7));

    SMAS(make.right.lessThanOrEqualTo(self.contentView.mas_right).offset(-78));

    }];

    //添加气泡内文字与气泡的约束

    [self.messageLabel mas_makeConstraints:^(MASConstraintMaker*make) {

    make.edges.mas_offset(UIEdgeInsetsMake(10,15,10,15));

    }];

    关键代码,就是上面这段了,这里我们借用Reveal来看一下约束关系,撇开SMAS是什么鬼先不说,可能比较难理解的就是lessThanOrEqualTo这句了,但是这句就是能让气泡伸缩自如的关键之一。

    即:label的左边界的X坐标值“小于等于”contentView的左边界的X坐标值。

    也就是说lable.width最大可以是contentView.�width - 78,最小可以是0。不知道这解释,大家能不能理解,但是不妨多用equal,�greaterThanOrEqualTo,lessThanOrEqualTo实验下。

    好了接下来讲一下SMAS是啥,看起来有点玄乎但是真相只有一个

    #define SMAS(x) [self.constraints addObject:x]

    没错,这就是一个宏而已,它的作用就是把约束保存在self.constraints这个数组中,那为啥要这么做呢,

    �由于我们一个cell要实现两种气泡方向(我方发出/对方发出),还是看�上上段代码,这里我们把气泡的左右约束都保存到了数组中,接下来我们只需要在合适的地方将约束卸载掉,然后再make新的约束即可,当然这里也可以用mas_remakeConstraints来实现,当然缺点就是每次都要把所有约束都重写一遍。这里可能会对这种用法有更详细的解释

    for(MASConstraint*constraint in self.constraints) {

    [constraint uninstall];

    }

    重新为气泡添加新的左右约束

    [self.bubbleImageView mas_makeConstraints:^(MASConstraintMaker*make) {

    if(direction == MessageDirection_RECEIVE) {

    SMAS(make.left.equalTo(self.avatarImageView.mas_right).offset(7));

    SMAS(make.right.lessThanOrEqualTo(self.contentView.mas_right).offset(-78));

    }else{

    SMAS(make.right.equalTo(self.avatarImageView.mas_left).offset(-7));

    SMAS(make.left.greaterThanOrEqualTo(self.contentView.mas_left).offset(78));

    }

    }];

      另外在这里普及一下为什么不能用mas_updateConstraints,mas_updateConstraints只能用于相同约束的情况下。

    例如:

    [self.retryBtn mas_makeConstraints:^(MASConstraintMaker*make) {

    make.centerY.equalTo(self.statusView.mas_centerY).offset(0);

    make.centerX.equalTo(self.statusView.mas_centerX).offset(0);

    }];

    [self.retryBtnmas_updateConstraints:^(MASConstraintMaker*make) {

    make.centerX.equalTo(self.statusView.mas_centerX).offset(100);

    }];

    简而言之,update只适用于更改offset之后的数值。�

      最后,�既然是tableview,那当然就少不了老生常谈的计算rowheight的问题。�在这里给大家推荐一个�自适应cell高度的神器FDTemplateLayoutCell,�只要是cell里的纵向约束添加完整,便可以自动计算并�缓存cell高度。当然在ios8+也可以使用tableview新增的estimatedHeightForRowAtIndexPath来估算高度。在这个项目里我选择了前者。具体的用法可以参考我之前写的一个demo:FDWithMasonryDemo。这样一来气泡的上下伸缩就so easy了~

    �这个项目�写了有几天了,接下来还会不断的完善,如果有小伙伴想加入的话可以私信我,或者fork这个项目。��

    �最后附上Github:TLMessage

    未完待续。。

    相关文章

      网友评论

      • 爱自由鹏:处理几种键盘隐藏显示逻辑,可以封装个方法吗,我们有8个按钮都可以调出键盘,和现在的QQ键盘界面一样,我用的键盘做的,有问题
        151ba12c22e5:@爱自由鹏 这是个待优化的地方,最近比较忙没有太多时间维护这个项目,如果你有兴趣可以forking这个项目贡献一些代码,不胜感激😊
      • 爱自由鹏:楼主,进入相册,左右滑动照片,有刷新问题呀,帮忙解决下
        151ba12c22e5:@爱自由鹏 photokit这个框架读取照片是异步的,会有些延时
        爱自由鹏:@timelessg 就是慢慢滑动 查看下一个图片的时候,下一张图片是没刷新出来的 卡了一下,然后等了一会才刷新出来
        151ba12c22e5:@timelessg 具体问题是什么呢?我这里ios9.0,看起来似乎没有问题
      • 爱自由鹏:发图片别人接收,然后他点击图片,即加载原始图片的时候,看不到原始图片,怎么回事
        爱自由鹏:@timelessg 我用sendMediaMessage这个方法发送图片是可以的,用sendMessage不可以,可能是融云不支持用sendMessage了,那我现在得再判断下,如果是图片就用sendMediaMessage,其他情况就用你封装的sendMessage
        151ba12c22e5:@爱自由鹏  先看看rcmessge里的url是不是对的,看看sdwebimage的setimagecomplete回调里有没有error,能拿到image的话麻烦再私信我一下,我check下
        爱自由鹏:@爱自由鹏 我发图片,别人点击图片的时候 拿不到RCImageMessage中的imageUrl,所以屏幕是黑的,为什么拿不到呀????
      • 风轻知道:给你的文采点个赞 :+1:
      • 闲来读者:一直发消息会崩溃
        151ba12c22e5:@闲来读者 已经修复多谢
        闲来读者:@timelessg Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer <TLTextMessageCell 0x14c915200> for the key path "sentStatus" from <RCMessage 0x14db02ce0> because it is not registered as an observer.'
        *** First throw call stack:
        (0x180f89900 0x1805f7f80 0x180f89848 0x18188d938 0x18188d414 0x1000e0194 0x185fbe1fc 0x185e9c788 0x185fc00b0 0x185cb7394 0x185cb6e90 0x185cb6d18 0x18368dc00 0x1005f1bb0 0x1005f7658 0x180f40bb0 0x180f3ea18 0x180e6d680 0x18237c088 0x185ce4d90 0x1000ea1a8 0x180a0e8b8)
        libc++abi.dylib: terminating with uncaught exception of type NSException
        151ba12c22e5:@闲来读者 可否把堆栈给我下
      • 向右奔跑:把代码放到代码框中
        151ba12c22e5:@向右奔跑 ok

      本文标题:iOS实现一个开源的IMKit

      本文链接:https://www.haomeiwen.com/subject/ywzwsttx.html