Files
peko-ios/docs/AttachmentModel_Analysis_Report.md

16 KiB
Raw Blame History

AttachmentModel 功能分析报告

目录

1. 概述

1.1 定义

AttachmentModel 是YuMi项目中用于处理NIMSDK自定义消息的核心数据模型它实现了NIMCustomAttachment协议用于在云信SDK中传输和处理各种自定义消息类型。

1.2 核心作用

  • 消息类型标识: 通过firstsecond字段标识不同的消息类型和子类型
  • 数据承载: 通过data字段承载具体的消息内容
  • 消息解析: 配合CustomAttachmentDecoder进行消息的编码和解码
  • 业务扩展: 支持各种业务场景的自定义消息处理

1.3 设计特点

  • 类型安全: 使用枚举定义所有消息类型,避免硬编码
  • 扩展性强: 支持新增消息类型而不影响现有代码
  • 统一接口: 所有自定义消息都通过统一的接口处理
  • 数据灵活: data字段支持任意类型的数据结构

2. AttachmentModel 核心结构

2.1 基础属性

@interface AttachmentModel : PIBaseModel<NIMCustomAttachment>

@property (nonatomic, strong) id data;           // 消息数据内容
@property (nonatomic, assign) int first;         // 消息类型标识
@property (nonatomic, assign) int second;        // 消息子类型标识
@property (nonatomic, assign) BOOL isBroadcast;  // 是否为广播消息
@property (nonatomic, assign) NSInteger seq;     // 本地序号,用于消息排序

@end

2.2 编码实现

- (NSString *)encodeAttachment {
    return [self toJSONString];
}

2.3 解码实现

// CustomAttachmentDecoder.m
- (id<NIMCustomAttachment>)decodeAttachment:(NSString *)content {
    id<NIMCustomAttachment> attachment;
    NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];
    
    if (data) {
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data
                                                             options:0
                                                               error:nil];
        if ([dict isKindOfClass:[NSDictionary class]]) {
            int first = [dict[@"first"] intValue];
            int second = [dict[@"second"] intValue];
            id originalData = dict[@"data"];

            AttachmentModel *model = [[AttachmentModel alloc] init];
            model.first = (short)first;
            model.second = (short)second;
            model.data = originalData;
            
            attachment = model;
        }
    }
    return attachment;
}

3. 消息类型分类

3.1 主要消息类型 (first字段)

3.1.1 基础功能类

类型值 类型名称 功能描述
2 CustomMessageType_Room_Tip 房间提示消息
3 CustomMessageType_Gift 礼物相关消息
5 CustomMessageType_Account 账户更新消息
6 CustomMessageType_Member_Online 关注主播上线通知
8 CustomMessageType_Queue 队列操作消息
9 CustomMessageType_Face 表情消息
10 CustomMessageType_Tweet 推文消息
12 CustomMessageType_AllMicroSend 全麦送礼物

3.1.2 房间管理类

类型值 类型名称 功能描述
15 CustomMessageType_Car_Notify 座驾相关通知
18 CustomMessageType_Kick_User 踢出房间消息
20 CustomMessageType_Update_RoomInfo 房间信息更新
30 CustomMessageType_Arrange_Mic 排麦相关消息
31 CustomMessageType_Room_PK 房间内PK消息
42 CustomMessageType_Room_GiftValue 房间礼物值同步

3.1.3 社交功能类

类型值 类型名称 功能描述
19 CustomMessageType_Secretary 小秘书消息
22 CustomMessageType_Application_Share 应用内分享
52 CustomMessageType_Monents 动态相关消息
60 CustomMessageType_RedPacket 红包相关消息
62 CustomMessageType_FindNew 发现萌新消息
64 CustomMessageType_CP CP礼物消息

3.1.4 游戏娱乐类

类型值 类型名称 功能描述
26 CustomMessageType_Candy_Tree 糖果树消息
63 CustomMessageType_RoomBoom 房间火箭消息
71 CustomMessageType_Tarot 塔罗牌消息
72 CustomMessageType_RoomPlay_Dating 相亲游戏消息
81 CustomMessageType_Room_Sailing 航海游戏消息
83 CustomMessageType_Across_Room_PK 跨房PK消息
97 CustomMessageType_Treasure_Fairy 精灵密藏消息

3.1.5 系统通知类

类型值 类型名称 功能描述
23 CustomMessageType_Message_Handle 系统通知消息
24 CustomMessageType_User_UpGrade 用户升级消息
49 CustomMessageType_Version_Update 版本升级消息
75 CustomMessageType_Chat_Risk_Alert 私聊风险提醒
76 CustomMessageType_First_Recharge_Reward 首充奖励消息
78 CustomMessageType_First_VisitorRecord 访客记录消息
92 CustomMessageType_Task_Complete 任务完成通知

3.2 子类型示例 (second字段)

3.2.1 礼物消息子类型

typedef NS_ENUM(NSUInteger, CustomMessageSubGift) {
    Custom_Message_Sub_Gift_Send = 31,           // 发送礼物
    Custom_Message_Sub_Gift_ChannelNotify = 32,  // 全服发送礼物
    Custom_Message_Sub_Gift_LuckySend = 34,      // 发送福袋礼物
    Custom_Message_Sub_Gift_EmbeddedStyle = 35,  // 发送嵌入式礼物
};

3.2.2 红包消息子类型

typedef NS_ENUM(NSUInteger, CustomMessageSubRedPacket) {
    Custom_Message_Sub_RoomGiftRedPacket = 601,      // 房间礼物红包
    Custom_Message_Sub_RoomDiamandRedPacket = 602,   // 房间钻石红包
    Custom_Message_Sub_AllGiftRedPacket = 603,       // 全服礼物红包
    Custom_Message_Sub_AllDiamandRedPacket = 604,    // 全服钻石红包
    Custom_Message_Sub_OpenRedPacketSuccess = 605,   // 抢红包成功
    Custom_Message_Sub_NewRoomDiamandRedPacket = 606, // 新版本房间钻石红包
    Custom_Message_Sub_LuckyPackage = 607,           // 最新版本房间红包推送
};

3.2.3 房间PK子类型

typedef NS_ENUM(NSUInteger, CustomMessageSubRoomPK) {
    Custom_Message_Sub_Room_PK_Non_Empty = 311,      // 从无人报名pk排麦到有人报名pk排麦
    Custom_Message_Sub_Room_PK_Empty = 312,          // 从有人报名pk排麦到无人报名pk排麦
    Custom_Message_Sub_Room_PK_Mode_Open = 313,      // 创建了pk模式
    Custom_Message_Sub_Room_PK_Mode_Close = 314,     // 关闭pk模式
    Custom_Message_Sub_Room_PK_Start = 315,          // pk开始
    Custom_Message_Sub_Room_PK_Result = 316,         // pk结果
    Custom_Message_Sub_Room_PK_Re_Start = 317,       // 重新开始
    Custom_Message_Sub_Room_PK_Manager_Up_Mic = 318, // 管理员邀请上麦
};

4. 使用场景分析

4.1 消息接收处理

4.1.1 私聊消息处理

// TabbarViewController.m
- (void)onRecvMessages:(NSArray<NIMMessage *> *)messages {
    for (NIMMessage *message in messages) {
        if (message.session.sessionType == NIMSessionTypeP2P) {
            if (message.messageType == NIMMessageTypeCustom) {
                NIMCustomObject *obj = (NIMCustomObject *)message.messageObject;
                if (obj.attachment != nil && [obj.attachment isKindOfClass:[AttachmentModel class]]) {
                    AttachmentModel *attachment = (AttachmentModel *)obj.attachment;
                    
                    // 处理发现萌新打招呼消息
                    if (attachment.first == CustomMessageType_FindNew && 
                        attachment.second == Custom_Message_Find_New_Greet_New_User) {
                        FindNewGreetMessageModel *greetInfo = [FindNewGreetMessageModel modelWithDictionary:attachment.data];
                        // 显示打招呼弹窗
                        [self showGreetAlert:greetInfo];
                    }
                }
            }
        }
    }
}

4.1.2 广播消息处理

// TabbarViewController.m
- (void)onReceiveBroadcastMessage:(NIMBroadcastMessage *)broadcastMessage {
    if (broadcastMessage.content) {
        NSDictionary *msgDictionary = [broadcastMessage.content toJSONObject];
        AttachmentModel *attachment = [AttachmentModel modelWithJSON:msgDictionary[@"body"]];
        
        // 处理红包消息
        if (attachment.first == CustomMessageType_RedPacket) {
            [self receiveRedPacketDealWithData:attachment];
        }
        // 处理版本更新消息
        else if (attachment.first == CustomMessageType_Version_Update && 
                 attachment.second == Custom_Message_Version_Update_Value) {
            [self handleVersionUpdate:attachment];
        }
    }
}

4.2 消息发送

4.2.1 创建自定义消息

// 创建礼物消息
AttachmentModel *attachment = [[AttachmentModel alloc] init];
attachment.first = CustomMessageType_Gift;
attachment.second = Custom_Message_Sub_Gift_Send;
attachment.data = @{
    @"giftId": @"123",
    @"giftName": @"玫瑰花",
    @"giftCount": @1,
    @"senderId": @"user123",
    @"receiverId": @"user456"
};

// 创建NIM消息
NIMCustomObject *customObject = [[NIMCustomObject alloc] init];
customObject.attachment = attachment;
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = customObject;

4.2.2 发送消息

// 发送到指定会话
NIMSession *session = [NIMSession session:@"receiverId" type:NIMSessionTypeP2P];
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];

4.3 消息内容显示

4.3.1 消息内容解析

// NIMMessageUtils.m
+ (NSString *)messageContent:(NIMMessage*)message {
    switch (message.messageType) {
        case NIMMessageTypeCustom: {
            NIMCustomObject *obj = (NIMCustomObject *)message.messageObject;
            AttachmentModel *attachment = (AttachmentModel *)obj.attachment;
            
            if (attachment.first == CustomMessageType_Secretary) {
                if (attachment.second == Custom_Message_Sub_Secretary_Router) {
                    return attachment.data[@"title"];
                }
            } else if (attachment.first == CustomMessageType_Gift) {
                if (attachment.second == Custom_Message_Sub_Gift_Send) {
                    return YMLocalizedString(@"NIMMessageUtils5"); // "发送了礼物"
                }
            } else if (attachment.first == CustomMessageType_FindNew && 
                       attachment.second == Custom_Message_Find_New_Greet_New_User) {
                NSString *text = attachment.data[@"message"];
                return text.length > 0 ? text : YMLocalizedString(@"NIMMessageUtils11");
            }
            // ... 其他消息类型处理
        }
        break;
    }
    return @"";
}

5. 功能模块分布

5.1 消息模块 (YMMessage)

  • 文件: AttachmentModel.h/m, CustomAttachmentDecoder.h/m
  • 功能: 消息模型定义、解码器实现
  • 使用: 所有自定义消息的基础结构

5.2 主界面模块 (YMTabbar)

  • 文件: TabbarViewController.m
  • 功能: 全局消息接收处理、广播消息处理
  • 使用: 处理发现萌新、红包、版本更新等全局消息

5.3 房间模块 (YMRoom)

  • 文件: 多个房间相关文件
  • 功能: 房间内消息处理、PK、礼物、火箭等
  • 使用: 处理房间内的各种互动消息

5.4 动态模块 (YMMonents)

  • 文件: XPMomentsViewController.m
  • 功能: 动态相关消息处理
  • 使用: 处理动态分享、审核等消息

5.5 个人中心模块 (YMMine)

  • 文件: 多个个人中心相关文件
  • 功能: 个人相关消息处理
  • 使用: 处理VIP、粉丝团、任务等个人消息

6. 关键实现细节

6.1 消息类型判断

// 判断是否为特定类型的消息
if (attachment.first == CustomMessageType_Gift && 
    attachment.second == Custom_Message_Sub_Gift_Send) {
    // 处理发送礼物消息
}

// 判断是否为系统消息
if (attachment.first == CustomMessageType_System_message) {
    // 处理系统消息
}

6.2 数据解析

// 从data字段解析具体数据
NSDictionary *giftData = attachment.data;
NSString *giftId = giftData[@"giftId"];
NSString *giftName = giftData[@"giftName"];
NSNumber *giftCount = giftData[@"giftCount"];

// 使用MJExtension进行模型转换
GiftModel *giftModel = [GiftModel modelWithDictionary:attachment.data];

6.3 消息过滤

// 根据分区ID过滤消息
NSString *partitionId = [NSString stringWithFormat:@"%@", attachment.data[@"partitionId"]];
if (![partitionId isEqualToString:self.userInfo.partitionId]) {
    return; // 不是当前分区的消息,忽略
}

6.4 消息排序

// 使用seq字段进行消息排序
@property (nonatomic, assign) NSInteger seq; // 本地序号,用于将一条消息分解为多条有次序的消息

7. 最佳实践

7.1 消息类型定义

  1. 使用枚举: 避免硬编码数字,提高代码可读性
  2. 分类管理: 按功能模块分类管理消息类型
  3. 版本兼容: 新增消息类型时保持向后兼容

7.2 消息处理

  1. 类型检查: 在处理消息前先检查类型
  2. 数据验证: 验证data字段的数据完整性
  3. 错误处理: 对解析失败的消息进行适当处理

7.3 性能优化

  1. 消息过滤: 根据业务需求过滤不需要的消息
  2. 内存管理: 及时释放不需要的消息对象
  3. 批量处理: 对大量消息进行批量处理

7.4 扩展性设计

  1. 模块化: 按功能模块组织消息处理逻辑
  2. 插件化: 支持新增消息类型而不影响现有代码
  3. 配置化: 通过配置文件管理消息类型

8. 总结

8.1 核心价值

AttachmentModel 作为YuMi项目的消息处理核心具有以下价值

  1. 统一接口: 为所有自定义消息提供统一的处理接口
  2. 类型安全: 通过枚举定义确保消息类型的类型安全
  3. 扩展性强: 支持灵活扩展新的消息类型
  4. 功能完整: 覆盖了社交、游戏、系统等各个业务场景

8.2 技术特点

  1. 协议实现: 实现了NIMSDK的NIMCustomAttachment协议
  2. JSON序列化: 支持JSON格式的消息编码和解码
  3. 模型转换: 支持与业务模型的相互转换
  4. 类型枚举: 使用枚举定义所有消息类型和子类型

8.3 业务覆盖

AttachmentModel 覆盖了YuMi项目的所有主要业务场景

  • 社交功能: 私聊、动态、关注等
  • 房间功能: PK、礼物、火箭、红包等
  • 游戏功能: 塔罗、航海、相亲等
  • 系统功能: 升级、任务、通知等
  • 商业功能: VIP、粉丝团、充值等

8.4 架构优势

  1. 解耦合: 消息处理逻辑与业务逻辑分离
  2. 可维护: 清晰的消息类型定义和处理流程
  3. 可测试: 每个消息类型都可以独立测试
  4. 可扩展: 新增功能时只需添加新的消息类型

AttachmentModel 是YuMi项目即时通讯功能的重要基础设施为项目的各种业务场景提供了强大而灵活的消息处理能力。


文档版本: 1.0
最后更新: 2024年12月
维护人员: 开发团队