用户
 找回密码
 立即注册

发帖

网易云信IM云服务,NIMKit浅析

[复制链接]
  • TA的每日心情
    慵懒
    2025-11-24 10:46
  • 27

    主题

    6

    回帖

    669

    积分

    管理员

    积分
    669
    发表于 2016-3-27 00:00:00
    最近把公司项目的聊天模块从”XMPP”转到”网易云信”官网github。在转的过程中,上手很快,基本上没遇到什么难题,很多程度上感谢云信的NIMKit。以前也接触过几个IM SDK服务商的代码,那个时候看他们的代码根本没什么欲望,但这次看云信的代码有种被吸引的感觉,恨不得一下子把它的代码全部看完,封装的很好,扩展性很强(ps:就我目前的水平只能说出这些优点)。对于一般的聊天UI完全可以满足,就算不用网易的IM SDK,但他们的代码真的值得一下(尽管他们的UIKit代码注释比较少)。
    在看本文之前,请先看一下他们官方的github简介
    Base tipscell的组成结构
    对于聊天”MessageCell”的介绍,一定要记住下面这张图片,以及相关参数的解释。5 ^5 X( P* o* \# ^# E
    005IevIrjw1f2bf6cvkjqj31bu0iktbg.jpg nimkit_cell
    ) K: Q' {: v; E0 \6 ^& W; E
    • 蓝色区域:为具体内容,如文字 UILabel ,图片 UIImageView 等 。(对应的NIMMessageModel对象的contentSize属性)。注:NIMMessageModel为消息(NIMMessage) 在NIMKit中的封装。这个封装主要是为了对计算结果和布局配置进行缓存,以避免反复的计算和读取相同的信息,从而提高应用性能。
    • 绿色区域:为消息的气泡,具体的内容和气泡之间会有一定的内间距,这里为 contentViewInsets 。(对应的NIMMessageModel对象的contentViewInsets属性)
    • 紫色区域:为整个 UITableViewCell ,具体的气泡和整个cell会有一定的内间距,这里为 cellInsets 。(对应的NIMMessageModel对象的bubbleViewInsets属性)
      6 ^1 S" @' f- u9 @* J" d
    config配置协议
    在聊天界面有几个config配置代理,先熟悉一下。
    • NIMSessionConfig:消息对应的session配置。如:录音、输入框、表情、更多等操作的选择;点击”+”号出来的多媒体按钮;是否禁用输入控件;输入控件的最大长度;输入控件的placeholder;一次最多消息的消息内容;间隔多久显示时间;语音红点是否禁用;是否自动切换成听筒模式;是否自动获取历史消息;消息数据提供器;消息的排版配置等。可以说这个是贯穿整个聊天模块的配置,修改聊天界面一般就得调整这里。
    • NIMCellLayoutConfig:消息对应的布局配置。我们可以在这个config里面根据消息类型是否显示头像、姓名、头像与姓名之间的margin等;然后你会在项目里面看到自定义消息类型对应的NTESSessionCustomLayoutConfig,以及default默认的配置NIMCellLayoutDefaultConfig;
    • NIMSessionContentConfig:消息内容配置。这个配置主要是为NIMSessionMessageContentView(请看下面对 聊天 NIMMessageCell.h 的介绍)对象为设置的。
      - x/ N9 |( C) s& N
    聊天 NIMMessageCell.h
    先来看看头文件定义的属性
    / m) z, u6 x  J4 C4 l
    1. @property (nonatomic, strong) NIMAvatarImageView *headImageView;* H' ~- p( o9 T: U9 c& J( T
    2. @property (nonatomic, strong) UILabel *nameLabel;                                 //姓名(群显示 个人不显示)& J/ t0 X- d) p/ P
    3. @property (nonatomic, strong) NIMSessionMessageContentView *bubbleView;           //内容区域) |1 t% |2 y5 ~. Z  t$ t( t# Z
    4. @property (nonatomic, strong) UIActivityIndicatorView *traningActivityIndicator;  //发送loading
      ; m' h9 ?7 ?* Y9 L9 p
    5. @property (nonatomic, strong) UIButton *retryButton;                              //重试
      ! I, A- O. X- V* s* m0 T7 Y2 P" g
    6. @property (nonatomic, strong) NIMBadgeView *audioPlayedIcon;                      //语音未读红点
    复制代码
    NIMSessionMessageContentView,顾名思义就是MessageCell的内容View(包括下面的bubble气泡View)。而 NIMSessionContentConfig 配置主要是配置 contentSize、contentViewInsets以及这个配置所应的 messageContentView 类名(NIMSessionMessageContentView的子类,每种聊天类型对应一个messageContentView)。注意,这里并没有提到 bubbleViewInsets,因为气泡隔cell的距离不会因不同类型而改变,我们只需在 cellLayoutConfig 里面处理即可,当然想要做到不同的话,也可以在 NIMSessionContentConfig 配置里面增加一个协议方法。注意 NIMSessionMessageContentView 是继承自 UIControl,这样不仅能处理点击事件,还能很好的处理点击高亮的效果。
    NIMSessionViewController(聊天回话控制器基类)
    先来看看最重要的计算高度方法
    + e# {+ {5 x& ]3 G9 P0 N
    1. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
      0 j9 ]1 f+ B  \0 G  g4 @
    2. {
      ! u+ o. z, M) l4 {8 ?! i5 o
    3.     CGFloat cellHeight = 0;
      5 @6 X2 b4 v! L
    4.     id modelInArray = [[_sessionDatasource modelArray] objectAtIndex:indexPath.row];7 ^2 j5 L+ h) b
    5.     if ([modelInArray isKindOfClass:[NIMMessageModel class]])  L  u$ q- P% o
    6.     {6 g7 L4 \" Y' S8 E' C
    7.         NIMMessageModel *model = (NIMMessageModel *)modelInArray;9 \: I3 x/ d5 p" W- n
    8.         NSAssert([model respondsToSelector:@selector(contentSize)], @"config must have a cell height value!!!");
      ; l/ I1 t, v6 w  h% x% G& T
    9.         [self layoutConfig:model];
      2 u7 L+ g  s& Y1 r$ v
    10.         CGSize size = model.contentSize;' C6 k; B& X# h4 q+ H1 K9 V4 S
    11.         UIEdgeInsets contentViewInsets = model.contentViewInsets;8 K( j3 j/ T. ]% [- m  e
    12.         UIEdgeInsets bubbleViewInsets  = model.bubbleViewInsets;
      . I7 q. x) h1 _
    13.         cellHeight = size.height + contentViewInsets.top + contentViewInsets.bottom + bubbleViewInsets.top + bubbleViewInsets.bottom;$ R/ q* S. K$ K+ ?, Q
    14.     }
      . w# ~/ H) o2 W" V( n) @
    15.     else if ([modelInArray isKindOfClass:[NIMTimestampModel class]])
      5 z5 o# ~* C. {$ p7 t. F
    16.     {* y3 `" @) D$ J, X3 V
    17.         cellHeight = [modelInArray height];
      7 e# i  ]' F1 J( h: J
    18.     }$ u6 _/ ^/ ]5 m# a! f6 I; M+ W
    19.     else3 j/ v, M$ l0 c$ r: q
    20.     {
      - E5 Y. h/ u; c8 u- E
    21.         NSAssert(0, @"not support model");) N+ w) u; X$ U, Q* ~7 \
    22.     }0 K0 k7 Y5 N( v
    23.     return cellHeight;
      $ O- ~3 c9 n; G
    24. }
    复制代码
    某个数据源所对应的高度就是三个颜色区域的高度之和(contentSize.height + contentViewInsets.top + contentViewInsets.bottom + bubbleViewInsets.top + bubbleViewInsets.bottom)。
    1 q+ y$ w6 v4 a4 \- J2 o3 N然后我们在来看看layoutConfig:方法:
    $ O) `% y  f6 ~
    1. - (void)layoutConfig:(NIMMessageModel *)model{
      ' l" G# e9 H7 s3 q# I% q
    2.     model.sessionConfig = self.sessionConfig;
      % ^) @6 w) G$ p; J. p+ n
    3.     if (model.layoutConfig == nil)
      ; ?6 b  ~, m0 z; u
    4.     {
      7 ^% l& }' ^" S1 K4 t! _3 h
    5.         id layoutConfig = nil;
      + }2 z3 w  ^! ~: e
    6.         if ([self.sessionConfig respondsToSelector:@selector(layoutConfigWithMessage:)]) {
      1 Z6 h/ c7 t4 P( d
    7.             layoutConfig = [self.sessionConfig layoutConfigWithMessage:model.message];9 a+ e% I7 _; C; |
    8.         }
      , i8 E$ O  x$ G  |- E: ^; ]) ?
    9.         if (!layoutConfig) {
      ; }, M* {! u3 e7 _6 p! E
    10.             layoutConfig = [NIMDefaultValueMaker sharedMaker].cellLayoutDefaultConfig;* A$ M. G# [9 W, O% l. H! R
    11.         }
      7 [) V/ ~. I3 n2 Y6 \' h0 D
    12.         model.layoutConfig = layoutConfig;
      / ~& E7 I1 S& j6 ]9 |
    13.     }
      2 o6 c5 ]/ F7 ], x2 E  e+ G
    14.     [model calculateContent:self.tableView.nim_width];
      " D: @& A0 b9 R8 R1 P. C" G4 R5 R
    15. }
    复制代码
    其实这里就是,先配置model的sessionConfig,然后配置layoutConfig,配置完后就去计算该model所对应内容的contentSize。注:layoutConfigWithMessage:方法是自定义消息类型需要处理,还有记得在写代码中做好判nil的处理,如果为nil的话给default值。
    好了,现在到了一个我当时比较蛋疼的地方了,请看下图  U$ |8 u7 a- {( |8 ^+ L8 ]8 N9 s
    005IevIrjw1f2bgtofy3yj30t50acdkr.jpg Image2
    , x( ~" A. I6 G2 @: b; k看到很多的方法,仔细看看,除了layoutConfig的配置方法以外,还有很多Attachment(Attachment 是属于自定义消息的配置协议)结尾的方法,其实这里应该只会提示NIMCellLayoutDefaultConfig和NTESSessionCustomLayoutConfig(NTESChatroomCellLayoutConfig聊天室的布局配置请忽略)才对,它们只是方法名相同,应该是Xcode抽风而导致的。
    NIMCellLayoutDefaultConfig计算contentSize
    先看三个相关部分的代码
    NIMCellLayoutDefaultConfig
    1. - (CGSize)contentSize:(NIMMessageModel *)model cellWidth:(CGFloat)cellWidth{
      # ~' ^) H* K+ g
    2.     , ]) P2 _; n: O3 [0 d; B1 N
    3.     idconfig = [[NIMSessionContentConfigFactory sharedFacotry] configBy:model.message];; _" }1 n8 _# p1 Z; ~
    4.     return [config contentSize:cellWidth];
      " g" W% j3 G. P$ ?
    5. }
        _: z/ q9 w5 Y) I+ x( w
    6. $ o" G( L- a0 N3 ?6 [
    7. - (NSString *)cellContent:(NIMMessageModel *)model{8 w5 N8 p% F7 u2 q0 S
    8.    
      * X& H8 r! l# ^# R6 Q5 k' [
    9.     idconfig = [[NIMSessionContentConfigFactory sharedFacotry] configBy:model.message];
      ! x- m* [" F; \, @! z7 H9 R
    10.     NSString *cellContent = [config cellContent];
      4 I5 c3 a1 X# R$ [3 V. n
    11.     return cellContent ? : @"NIMSessionUnknowContentView";+ r( p. f: e( ?; H! y
    12. }
      0 _5 @: s  S5 ]! L; r$ i

    13. # X6 P* [7 |7 A: H* A

    14. ! S3 I, U: f. r& P: m2 @
    15. - (UIEdgeInsets)contentViewInsets:(NIMMessageModel *)model{7 R$ `$ G/ S' U$ m! l5 ]0 ^  v% u4 Y
    16.     idconfig = [[NIMSessionContentConfigFactory sharedFacotry] configBy:model.message];& W6 o8 ~( L8 W' F4 C( e, X$ M/ q
    17.     return [config contentViewInsets];
      7 B7 F+ n' J! y+ n
    18. }
    复制代码
    NIMSessionContentConfigFactory
    1. - (instancetype)init( C# ^$ P- x: s; v
    2. {
      - Z9 {) e% [; |2 R2 @
    3.     if (self = [super init])
      $ E: l4 l0 r8 T$ _( \* Q6 I
    4.     {3 \0 q  Y( i" S  F3 o0 f
    5.         _dict = @{@(NIMMessageTypeText)         :       [NIMTextContentConfig new],
      / M4 x( O: c7 h+ b, Y( ?
    6.                   @(NIMMessageTypeImage)        :       [NIMImageContentConfig new],7 T; N4 g9 R& [# x$ h* i3 C/ b
    7.                   @(NIMMessageTypeAudio)        :       [NIMAudioContentConfig new],
      " I" H6 @( f. M8 F4 b9 g- U5 D
    8.                   @(NIMMessageTypeVideo)        :       [NIMVideoContentConfig new],
      7 s: E# J: g) p  H  @3 n
    9.                   @(NIMMessageTypeFile)         :       [NIMFileContentConfig new],
      9 N3 ^8 Z4 t2 t* @+ e& e
    10.                   @(NIMMessageTypeLocation)     :       [NIMLocationContentConfig new],9 U9 l) S* m7 ]# ?& L9 O/ B, i5 Z, x  d
    11.                   @(NIMMessageTypeNotification) :       [NIMNotificationContentConfig new],
      # ?6 d% J; J5 i! B' A
    12.                   @(NIMMessageTypeTip)          :       [NIMTipContentConfig new]};4 C3 Y9 _2 m' j# D. y
    13.     }
      2 H3 e) H1 |3 M: [. K
    14.     return self;5 d5 U' K1 `: A5 B
    15. }4 n9 \5 M. G* s/ j+ `# y3 ?. ]

    16. # t  R4 o3 _+ V* F5 c, _) ^6 b
    17. - (id)configBy:(NIMMessage *)message+ x1 j2 K/ R$ }0 y6 S" n
    18. {, R+ j2 X# A) A# X1 G! ~
    19.     NIMMessageType type = message.messageType;
      ( `- k: M" }5 E- r+ W5 ^
    20.     idconfig = [_dict objectForKey:@(type)];6 j4 V/ ~2 E3 E8 H* s2 r
    21.     if (config == nil)" i/ D4 v5 d" [7 k9 ~2 r  l1 ]
    22.     {
      , W  y* o) G$ l% [  z
    23.         config = [NIMUnsupportContentConfig sharedConfig];- [/ x% X) |$ V
    24.     }3 b$ l# r, k. `6 n0 a; G$ \
    25.     if ([config isKindOfClass:[NIMBaseSessionContentConfig class]])+ Y+ ~3 P9 z% D: S: I; a
    26.     {
      3 O0 j! {4 {: N6 m5 ]4 J9 v7 \
    27.         [(NIMBaseSessionContentConfig *)config setMessage:message];
      1 m3 H3 y5 X: v- b  L- d; E
    28.     }! D( W& s' J5 ^1 ?
    29.     return config;
      6 _4 A7 ~. x  `' ], V, A& ~
    30. }
    复制代码
    NIMImageContentConfig
    1. #import "NIMBaseSessionContentConfig.h"/ d3 C/ z- k; O3 c1 A

    2. 1 q; H4 E0 l4 @/ B! ?3 h1 Z
    3. @interface NIMTextContentConfig : NIMBaseSessionContentConfig2 q) Q& a, l% S1 g- O

    4. 0 V/ ?) F0 V: O+ X( q0 P* r
    5. @end
    复制代码
    1. @interface NIMTextContentConfig()* M! t5 l+ D9 m; a3 s
    2. 9 u5 n! A; z/ Y2 ~2 |2 n& g
    3. @property (nonatomic,strong) NIMAttributedLabel *label;
      6 |8 e0 D9 p8 i( Z( ]8 t+ ~0 F
    4. 8 V! Z" \' ^4 \: S  e$ m9 L9 m3 d
    5. @end
      $ x% o$ S+ s6 x4 h6 K9 W- I- U/ H; P

    6. # o% F2 y/ G) b

    7. / x6 r- @  N% Z4 |- H5 C  M1 G6 k) J
    8. @implementation NIMTextContentConfig8 s8 o7 M: i+ k* b# C/ Y3 ^# \
    9. 8 t2 ^. f$ |% U3 j" f) L  [& t
    10. - (CGSize)contentSize:(CGFloat)cellWidth! T" _+ ?* A* f7 Q
    11. {9 F7 u8 I! \2 y4 }' [
    12.     NSString *text = self.message.text;
      3 Y. ~3 j3 i5 J0 w* y; y9 H+ \
    13.     [self.label nim_setText:text];
      + ?" G  V6 @& N- n+ I9 ~; p0 C: b
    14.     + J5 Q' v& l+ D; a! ~
    15.     CGFloat msgBubbleMaxWidth    = (cellWidth - 130);' H( ]4 E  Z9 R0 @* L5 @8 `
    16.     CGFloat bubbleLeftToContent  = 14;/ @5 M% h7 ?4 E) y: T
    17.     CGFloat contentRightToBubble = 14;* h0 u. r. z7 J: n( S* k
    18.     CGFloat msgContentMaxWidth = (msgBubbleMaxWidth - contentRightToBubble - bubbleLeftToContent);
      . `- r" G! O/ j0 t0 y% b# E& X
    19.     return [self.label sizeThatFits:CGSizeMake(msgContentMaxWidth, CGFLOAT_MAX)];
      & z$ T% O2 M$ T5 {) y
    20. }( w+ f. K2 t$ i" R' d: R4 a: E  l+ W
    21. 0 X. }' K3 V1 }  Q4 I) U
    22. - (NSString *)cellContent
      : Y, s( q5 z& x& d2 `- a
    23. {
      1 E" T8 D; d2 d; b* H2 p  ?6 F* J
    24.     return @"NIMSessionTextContentView";3 K+ L" V( v! a1 r3 j* U
    25. }9 n" ]; }0 k3 l. Y( O9 e
    26. % p  _- p9 `' z
    27. - (UIEdgeInsets)contentViewInsets
      5 \! {0 \& N' o% A
    28. {7 T+ [* [" x: {3 N- h) Z
    29.     return self.message.isOutgoingMsg ? UIEdgeInsetsMake(11,11,9,15) : UIEdgeInsetsMake(11,15,9,9);( Y( d8 P0 B, K
    30. }
      1 ]9 Y! k1 w7 n. h2 x' J0 p7 ~- A2 \

    31. ! L! H- L% e/ {) o, x
    32. 8 G; \$ I/ I; j8 R! e4 r
    33. - (NIMAttributedLabel *)label
      ' h; A7 T3 u0 |& @+ W: }
    34. {
      " O, a" [$ `3 P) l3 x
    35.     if (_label) {
      - Z7 i2 ~' ?3 [8 a3 v1 A
    36.         return _label;+ A) d7 c9 @) \$ h5 l7 j" v8 x
    37.     }7 K2 Y: {% J. S) @1 [( G) P8 c
    38.     _label = [[NIMAttributedLabel alloc] initWithFrame:CGRectZero];
      # C# b; J% j2 d, O9 Q
    39.     _label.font = [UIFont systemFontOfSize:NIMKit_Message_Font_Size];
      1 G' @. b  q) j1 m* i) I( ^
    40.     return _label;6 {- Y4 s! C2 K! s
    41. }8 b: [' g$ R8 f; N' E7 X
    42. @end
    复制代码
    这里就是实现了NIMSessionContentConfig配置协议,我举例一个文本消息类型的sessionContentView的处理方式,其他类型是一样的处理方法,实现相关配置协议方法即可。你可能会想到如果某个sessionContentView上面的元素有很多时该怎么处理,我该不会把某个sessionContentView的元素都定义一次,然后全部赋值再计算contentSize么?我将会在说自定义消息类型的时候谈谈我简单的处理方式。2 m: o8 P. I: j# b
    这里我个人觉得有两点可以改变一下。
    • NIMBaseSessionContentConfig的NIMMessage对象应该改为NIMMessageModel对象比较好。因为我需要用到contentSize,根据contentSize来设置控件的宽度适应屏幕。所以我在自定义的消息里面,将NTESCustomAttachmentInfo协议需要传入的NIMMessage对象改为NIMMessageModel对象。
    • 在返回contentView类名时,改为NSStringFromClass([NIMSessionTextContentView Class])会好点,怕输入字符串时时产生错误嘛。% ]) `( b, \4 v. l9 j; ~" e1 t
    在NIMSessionContentConfigFactory类里面定义了基本消息类型所对应的contentConfig配置协议(注意,在云信demo里面,每个sessionContentView都对应一个sessionContentConfig)。请看NIMUnsupportContentConfig判nil处理,如果没有这段判断处理,你在添加自定义消息时候,忘记在 NTESSessionCustomLayoutConfig类的supportAttachmentType方法里面添加你的自定义消息,程序就会崩溃。ps:防止崩溃,请从细节做起,谢谢!
    那NIMCellLayoutDefaultConfig计算contentSize就简单明了了,就是调用相关 sessionContentConfig 的方法嘛。
    NNTESSessionCustomContentConfig计算contentSize
    当我们看到NTESSessionCustomLayoutConfig类时,有两个地方是值得我们注意,也是与NIMCellLayoutDefaultConfig不同的地方。
    • 一个NTESSessionCustomContentConfig类的属性
    • supportAttachmentType 内部方法,用来获取customLayoutConfig直接的类型。
      7 m: _' x8 w+ l: j) g  D' H9 O
    NTESSessionCustomContentConfig
    它有一个NIMMessage类型的public属性,而在介绍NIMBaseSessionContentConfig配置协议时,我有说过建议将它的NIMMessage对象改为NIMMessageModel对象,在这里我也同样建议,原因上面有提过。
    : K- M6 {, t! b4 f1 Z- l请看它的.m文件:
    0 }' @7 p; a) M' X( r7 e
    1. @interface NTESSessionCustomContentConfig()' g$ [) T  {# s
    2. ; F5 X+ K1 [  z3 d
    3. @property (nonatomic, strong) id attachmentInfo;6 Y& K7 N" g& |  M) u" s( V) w9 g, T8 }

    4. / F- u, \# B$ e
    5. @end2 Y4 o  c$ b, \# }( Q$ ~1 @
    6.   }% V; D& m. k6 J) M3 ^
    7. @implementation NTESSessionCustomContentConfig, \! b; ?9 p' t) `# h
    8. / Q/ s# L! O- j0 R
    9. - (void)setMessage:(NIMMessage *)message* \) G+ _) g' ]+ b' q; M
    10. {; A) F. ^- t2 z6 x& [. s: _
    11.     NIMCustomObject *object = message.messageObject;1 U7 q- _  t/ B! ]2 @
    12.     _message = message;* A, c3 N- Q) A- [' R# x* B
    13.     _attachmentInfo = (id)object.attachment;
      / f3 i# H* \, L+ P3 |: }, [
    14. }7 G/ N5 u3 c! m; ^3 Z

    15. , g/ g6 ]) e& [- ~: v0 w9 O
    16. - (CGSize)contentSize:(CGFloat)cellWidth
      3 K! K& r# V  F
    17. {. Y7 Y3 r2 v4 L; r7 n: H2 |- h
    18.     return [self.attachmentInfo contentSize:self.message cellWidth:cellWidth];
      ) P! t2 y/ h6 o. H) O, r4 U0 b
    19. }
      * z$ Y$ M- V; j4 r

    20. 8 k+ ~# a) [' V4 p/ p' i# [
    21. - (NSString *)cellContent8 t+ O: N# z- r' T
    22. {
      + H8 u9 _! D1 V( `2 w, ]( M6 {" G* F
    23.     return [self.attachmentInfo cellContent:self.message];  }- L9 D6 g$ D- @5 M# c
    24. }( v6 T( Q% H' M5 t; N9 t9 @' u
    25. " [$ o- {& S, s1 H
    26. - (UIEdgeInsets)contentViewInsets7 U( m) a- p% Y( B
    27. {
      + B4 C6 Z" P- S  e& }4 m
    28.     return [self.attachmentInfo contentViewInsets:self.message];
      , ^+ `- H6 r3 _7 Z
    29. }, Y# l4 H% D/ a" E$ a
    30. * J: F1 w: O, y
    31. @end
    复制代码
    attachmentInfo对象代表不同类型的自定义消息,只要它遵守NTESCustomAttachmentInfo协议即可。(ps:其实NTESCustomAttachmentInfo协议就相当于上面基本消息类型所对应的NIMSessionContentConfig协议;注:这里所谓的基本消息类型,即云信SDK已定义的消息类型,相对于自定义消息类型而言而已。)
    下面来看看 NTESCustomAttachmentInfo 协议(已添加注释)。
    ! ~* O6 B: X1 L- c$ D
    1. @protocol NTESCustomAttachmentInfo " ~/ D" B0 f- i4 X& |  U- b* @" `
    2.   n; k6 I/ V# z% {; v  M
    3. @optional3 O/ P! c4 L2 Z  h& i
    4. /// contentView类名2 E. e& F- {- W2 W
    5. - (NSString *)cellContent:(NIMMessage *)message;
      * N1 x1 C/ l5 f% U: d( e! f
    6. /// contentSize
      % F* Z  o$ V) U* B8 o
    7. - (CGSize)contentSize:(NIMMessage *)message cellWidth:(CGFloat)width;
      ; P( Q0 f: k7 g3 y4 z2 k
    8. /// 内容距离bubble气泡的相关距离
      9 H6 b- \5 I/ i, i6 u
    9. - (UIEdgeInsets)contentViewInsets:(NIMMessage *)message;
        l0 o( H. z3 J: z
    10. /// 格式化消息 某些消息需要在最近回话列表特殊文字 如:收到一段文字,但是需要显示[系统消息]6 F8 i$ ?# w! Z0 @$ p- T' z4 Z. ~; g
    11. - (NSString *)formatedMessage;- H  j% H( u) F
    12. /// 封面图片 如果一个视频 得显示一张图片在界面
      3 m  [" |0 W: n# b
    13. - (UIImage *)showCoverImage;
      $ g3 s1 D+ K4 |
    14. /// 设置封面图片; ~: p0 q' o( b9 s' n
    15. - (void)setShowCoverImage:(UIImage *)image;
    复制代码
    在这里我提出两点建议
    • NIMMessage对象改为NIMMessageModel对象;
    • cellContent:、contentSize: cellWidth:、contentViewInsets:这三个方法改为@required类型的;方法名前面加上attachmentInfo与NIMSessionContentConfig协议的相关方法作为区分。
      ; @3 N' e) }' G0 `
    复杂自定义sessionContentView的简单处理方式
    上面在介绍NIMBaseSessionContentConfig配置协议时,我有提到如果某个sessionContentView上面的元素有很多时该怎么处理。下面我说说我的处理方式。
    • 把计算contentSize和contentViewInsets的方法丢到contentView里面,这样一来,那么只要在attachMentInfo里面调用所属contentView的计算方法。
    • 我会在NIMSessionMessageContentView类里面增加两个方法
      1. - (CGSize)attachmentInfoViewContentSize:(NIMMessageModel *)messageModel cellWidth:(CGFloat)width;2 _# `- p. i; o1 E4 X& j
      2. - (UIEdgeInsets)attachmentInfoViewcontentViewInsets:(NIMMessageModel *)messageModel;
      复制代码

      . G3 v3 T. g) x. D2 q  v
    • 在具体的contentView里面,我定义方法,它有一个Bool类型的isInit(是否初始化)入参,在这个方法里面我创建和实例变量一样的临时变量,当attachmentInfoViewContentSize: cellWidth方法调用它时,我只是为了方便计算contentSize,如果是initSessionMessageContentView方法调用时,我就将相应的临时变量赋值给例变量。

      * Q* K( ?* w) f
    原文链接:http://joakimliu.github.io/2016/03/27/NIMKit%E6%B5%85%E6%9E%90/
    使用道具 举报 回复
    严禁恶意灌水!!!拒绝伸手党!!!
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    ض