Files
peko-ios/docs/PublicRoomManager_Usage_Guide.md

6.3 KiB
Raw Blame History

PublicRoomManager 使用指南

概述

PublicRoomManager 是一个常驻单例,负责管理用户进入公共聊天房间的逻辑。它会在用户登录成功后自动初始化,并在用户登出时自动清理。

主要功能

  1. 自动初始化: 用户登录成功后自动初始化
  2. 自动进房: 根据用户的分区ID自动进入对应的公共聊天房间
  3. 消息监听: 监听公共房间的消息
  4. 自动清理: 用户登出时自动退出房间并清理状态
  5. 用户切换处理: 支持多次登出-登录的重置情况

核心特性

1. 生命周期管理

// 初始化(在用户登录成功后自动调用)
[[PublicRoomManager sharedManager] initialize];

// 重置(在用户登出时自动调用)
[[PublicRoomManager sharedManager] reset];

2. 状态查询

// 检查是否已初始化
BOOL isInitialized = [[PublicRoomManager sharedManager] isInitialized];

// 检查是否已在公共房间中
BOOL isInPublicRoom = [[PublicRoomManager sharedManager] isInPublicRoom];

// 获取当前公共房间ID
NSString *roomId = [[PublicRoomManager sharedManager] currentPublicRoomId];

3. 手动控制

// 手动进入公共房间
[[PublicRoomManager sharedManager] enterPublicRoomWithCompletion:^(NSError * _Nullable error) {
    if (error) {
        NSLog(@"进入公共房间失败: %@", error);
    } else {
        NSLog(@"进入公共房间成功");
    }
}];

// 手动退出公共房间
[[PublicRoomManager sharedManager] exitPublicRoomWithCompletion:^(NSError * _Nullable error) {
    if (error) {
        NSLog(@"退出公共房间失败: %@", error);
    } else {
        NSLog(@"退出公共房间成功");
    }
}];

集成点

1. 登录流程集成

PILoginManager.m 的登录成功回调中添加:

// 初始化公共房间管理器
[[PublicRoomManager sharedManager] initialize];

2. 登出流程集成

BaseMvpPresenter.m 的 logout 方法中添加:

// 重置公共房间管理器
[[PublicRoomManager sharedManager] reset];

3. 用户信息更新集成

TabbarViewController.mgetUserInfoSuccess 方法中添加:

// 更新公共房间管理器的用户信息
[[PublicRoomManager sharedManager] updateUserInfo:userInfo];

4. 配置更新集成

ClientConfig.m 的配置加载完成后添加:

// 通知公共房间管理器配置已更新
[[PublicRoomManager sharedManager] updateConfig];

工作原理

1. 初始化流程

  1. 检查用户是否已登录
  2. 检查用户信息是否完整(包含 partitionId
  3. 检查配置信息是否已加载(包含 publicChatRoomIdMap
  4. 注册云信消息代理
  5. 根据 partitionId 获取对应的 roomId
  6. 进入公共聊天房间

2. 进房流程

  1. 创建 NIMChatroomEnterRequest
  2. 设置用户扩展信息(头像、昵称、等级等)
  3. 调用云信 SDK 进入房间
  4. 处理进房成功/失败回调

3. 消息处理

  1. 实现 NIMChatManagerDelegate
  2. 过滤公共房间消息
  3. 处理消息内容

4. 清理流程

  1. 退出公共聊天房间
  2. 移除云信代理
  3. 重置所有状态

配置要求

1. 用户信息要求

用户信息必须包含 partitionId 字段:

UserInfoModel *userInfo = [AccountInfoStorage instance].getHomeUserInfo;
NSString *partitionId = userInfo.partitionId; // 必须存在

2. 配置信息要求

配置信息必须包含 publicChatRoomIdMap 字段:

ClientDataModel *configInfo = [ClientConfig shareConfig].configInfo;
NSDictionary *publicChatRoomIdMap = configInfo.publicChatRoomIdMap; // 必须存在

publicChatRoomIdMap 的格式应该是:

{
  "1": "roomId1",  // 分区1对应的房间ID
  "2": "roomId2",  // 分区2对应的房间ID
  "3": "roomId3"   // 分区3对应的房间ID
}

错误处理

1. 初始化失败

  • 用户未登录:等待用户登录
  • 用户信息不完整:等待用户信息更新
  • 配置信息未加载:等待配置更新

2. 进房失败

  • 网络错误:记录日志,可重试
  • 房间不存在:记录日志,跳过
  • 权限不足:记录日志,跳过

3. 用户切换

  • 检测到用户ID变化时自动重置
  • 清理旧用户状态
  • 重新初始化新用户

日志输出

PublicRoomManager 会输出详细的日志信息:

PublicRoomManager: 初始化成功用户ID: 123456, 分区ID: 1
PublicRoomManager: 尝试进入公共房间分区ID: 1, 房间ID: roomId1
PublicRoomManager: 进入公共房间成功房间ID: roomId1
PublicRoomManager: 收到公共房间消息: Hello World
PublicRoomManager: 检测到用户切换,重置管理器
PublicRoomManager: 开始重置
PublicRoomManager: 退出公共房间成功
PublicRoomManager: 重置完成

注意事项

  1. 线程安全: 所有操作都在主线程执行
  2. 内存管理: 使用单例模式,避免内存泄漏
  3. 错误恢复: 支持自动重试和错误恢复
  4. 状态同步: 确保状态与实际云信状态同步
  5. 性能优化: 避免重复初始化和不必要的操作

扩展功能

1. 消息处理扩展

可以在 onRecvMessages 方法中添加自定义的消息处理逻辑:

- (void)onRecvMessages:(NSArray<NIMMessage *> *)messages {
    for (NIMMessage *message in messages) {
        if (message.session.sessionType == NIMSessionTypeChatroom) {
            NSString *sessionId = message.session.sessionId;
            if ([sessionId isEqualToString:self.currentPublicRoomId]) {
                // 添加自定义消息处理逻辑
                [self handlePublicRoomMessage:message];
            }
        }
    }
}

2. 状态监听扩展

可以添加状态变化的通知:

// 在状态变化时发送通知
[[NSNotificationCenter defaultCenter] postNotificationName:@"PublicRoomManagerStateChanged" 
                                                    object:nil 
                                                  userInfo:@{@"isInPublicRoom": @(self.isInPublicRoom)}];

3. 重试机制扩展

可以添加更复杂的重试逻辑:

- (void)retryEnterPublicRoom {
    if (self.retryCount < 3) {
        self.retryCount++;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self tryEnterPublicRoom];
        });
    }
}