常看

关于云信聊天页面的分析

2020-02-11  本文已影响0人  曾柏超

具体文档请参考 云信文档

目录

/*
                                            NIMSessionViewController 类关系图
 
 
             .........................................................................
             .                                                                       .
             .                                                                       .
             .                                                                       .                  | ---> [NIMSessionDatasource]
             .                                                                       .
             .                                                       | ---> [NIMSessionInteractor] -->  |
             .
             .                                                                                          | ---> [NIMSessionLayout]
             .
             ↓
  [NIMSessionViewController]-------> [NIMSessionConfigurator] -----> |
             |                (把tableView的数据源和cell 的样式的代码抽取出来了)
             |
             |
             |
             ↓                                                       | ---> [NIMSessionTableAdapter]
       [UITableView]                                                              .
            ↑                                                                     .
            .                                                                     .
            .                                                                     .
            .......................................................................
 */

0. 关于  NIMSessionConfigurator 解耦  NIMSessionViewController 的方式
@implementation NIMSessionViewController
- (void)setupConfigurator
{
    _configurator = [[NIMSessionConfigurator alloc] init];
    [_configurator setup:self];
    
    BOOL needProximityMonitor = [self needProximityMonitor];
    [[NIMSDK sharedSDK].mediaManager setNeedProximityMonitor:needProximityMonitor];
}

@end
一.设置头像
@interface NIMAvatarImageView()

@property (nonatomic,strong) UIImageView *imageView;

@end

@implementation NIMAvatarImageView


- (void)setAvatarByMessage:(NIMMessage *)message
{
    NIMKitInfoFetchOption *option = [[NIMKitInfoFetchOption alloc] init];
    option.message = message;
    NSString *from = nil;
    if (message.messageType == NIMMessageTypeRobot)
    {
        NIMRobotObject *object = (NIMRobotObject *)message.messageObject;
        if (object.isFromRobot)
        {
            from = object.robotId;
        }
    }
    if (!from)
    {
        from = message.from;
    }
    NIMKitInfo *info = [[NIMKit sharedKit] infoByUser:from option:option];
    NSURL *url = info.avatarUrlString ? [NSURL URLWithString:info.avatarUrlString] : nil;
    [self nim_setImageWithURL:url placeholderImage:info.avatarImage];
}

@end

二. 关于cell 
cell 的代码全部封装在 NIMSessionTableAdapter 和 NIMMessageCellFactory 

@implementation NIMSessionTableAdapter

- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = nil;
    id model = [[self.interactor items] objectAtIndex:indexPath.row];
    if ([model isKindOfClass:[NIMMessageModel class]]) {
        cell = [self.cellFactory cellInTable:tableView
                                   forMessageMode:model];
        [(NIMMessageCell *)cell setDelegate:self.delegate];
        [(NIMMessageCell *)cell refreshData:model];
    }
    else if ([model isKindOfClass:[NIMTimestampModel class]])
    {
        cell = [self.cellFactory cellInTable:tableView
                                     forTimeModel:model];
    }
    else
    {
        NSAssert(0, @"not support model");
    }
    return cell;
}

@end


@implementation NIMMessageCellFactory
 
- (NIMMessageCell *)cellInTable:(UITableView*)tableView
                 forMessageMode:(NIMMessageModel *)model
{
    id<NIMCellLayoutConfig> layoutConfig = [[NIMKit sharedKit] layoutConfig];
    NSString *identity = [layoutConfig cellContent:model];
    NIMMessageCell *cell = [tableView dequeueReusableCellWithIdentifier:identity];
    if (!cell) {
        NSString *clz = @"NIMMessageCell";
        [tableView registerClass:NSClassFromString(clz) forCellReuseIdentifier:identity];
        cell = [tableView dequeueReusableCellWithIdentifier:identity];
    }    
    return (NIMMessageCell *)cell;
}

- (NIMSessionTimestampCell *)cellInTable:(UITableView *)tableView
                            forTimeModel:(NIMTimestampModel *)model
{
    NSString *identity = @"time";
    NIMSessionTimestampCell *cell = [tableView dequeueReusableCellWithIdentifier:identity];
    if (!cell) {
        NSString *clz = @"NIMSessionTimestampCell";
        [tableView registerClass:NSClassFromString(clz) forCellReuseIdentifier:identity];
        cell = [tableView dequeueReusableCellWithIdentifier:identity];
    }
    [cell refreshData:model];
    return (NIMSessionTimestampCell *)cell;
}
@end
三. 关于tableView 的frame

@implementation NIMSessionLayoutImpl
- (void)adjustTableView
{
    //输入框是否弹起
    BOOL inputViewUp = NO;
    switch (self.inputView.status)
    {
        case NIMInputStatusText:
            inputViewUp = [NIMKitKeyboardInfo instance].isVisiable;
            break;
        case NIMInputStatusAudio:
            inputViewUp = NO;
            break;
        case NIMInputStatusMore:
        case NIMInputStatusEmoticon:
            inputViewUp = YES;
        default:
            break;
    }
    self.tableView.userInteractionEnabled = !inputViewUp;
    CGRect rect = self.tableView.frame;
    
    //tableview 的位置
    UIView *superView = self.tableView.superview;
    UIEdgeInsets safeAreaInsets = UIEdgeInsetsZero;
    if (@available(iOS 11.0, *))
    {
        safeAreaInsets = superView.safeAreaInsets;
    }
    
    CGFloat containerSafeHeight = self.tableView.superview.frame.size.height - safeAreaInsets.bottom;
    
    rect.size.height = containerSafeHeight - self.inputView.toolBar.nim_height;
    
    
    //tableview 的内容 inset
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    CGFloat visiableHeight = 0;
    if (@available(iOS 11.0, *))
    {
        contentInsets = self.tableView.adjustedContentInset;
    }
    else
    {
        contentInsets = self.tableView.contentInset;
    }
    
    //如果气泡过少,少于总高度,输入框视图需要顶到最后一个气泡的下面。
    visiableHeight = visiableHeight + self.tableView.contentSize.height + contentInsets.top + contentInsets.bottom;
    visiableHeight = MIN(visiableHeight, rect.size.height);
    
    rect.origin.y    = containerSafeHeight - visiableHeight - self.inputView.nim_height;
    rect.origin.y    = rect.origin.y > 0? 0 : rect.origin.y;
    
    
    BOOL tableChanged = !CGRectEqualToRect(self.tableView.frame, rect);
    if (tableChanged)
    {
        [self.tableView setFrame:rect];
        [self.tableView nim_scrollToBottom:YES];
    }
}
@end
四. 关于数据源
 
@implementation NIMSessionMsgDatasource
- (NSArray<NIMMessageModel *> *)modelsWithMessages:(NSArray<NIMMessage *> *)messages
{
    NSMutableArray *array = [[NSMutableArray alloc] init];
    for (NIMMessage *message in messages) {
        NIMMessageModel *model = [[NIMMessageModel alloc] initWithMessage:message];
        [array addObject:model];
    }
    return array;
}

@end

五. 关于消息的扩展

@implementation NIMSessionInteractorImpl

#pragma mark - 消息收发接口
- (void)sendMessage:(NIMMessage *)message
{
    [[[NIMSDK sharedSDK] chatManager] sendMessage:[self addExt:message] toSession:_session error:nil];
}
- (NIMMessage *)addExt:(NIMMessage *)msg
{
    NSDictionary *ext = @{
                          @"name": name,
                          @"sex": sex,
                          };
    msg.remoteExt = ext;
    NSLog(@"msg.remoteExt---%@",msg.remoteExt);
    return msg;
}

@end

上一篇下一篇

猜你喜欢

热点阅读