16 KiB
16 KiB
NIMSDK 集成说明文档
目录
- 1. 项目概述
- 2. NIMSDK导入配置
- 3. NIMSDK初始化流程
- 4. 关键配置参数说明
- 5. 自定义消息处理
- 6. 登录管理
- 7. 消息接收处理
- 8. 推送通知集成
- 9. 最佳实践
- 10. 常见问题
1. 项目概述
1.1 项目简介
YuMi是一个基于iOS平台的社交应用,使用Objective-C开发,采用MVP架构模式。项目集成了网易云信SDK(NIMSDK)用于实现即时通讯功能。
1.2 技术栈
- 开发语言: Objective-C
- 架构模式: MVP (Model-View-Presenter)
- 即时通讯: 网易云信 NIMSDK_LITE
- 依赖管理: CocoaPods
- 最低支持版本: iOS 11.0
1.3 主要功能模块
- 用户登录注册
- 即时消息通讯
- 聊天室功能
- 动态发布
- 个人中心
- 房间直播
2. NIMSDK导入配置
2.1 Podfile配置
在项目的Podfile
中添加NIMSDK依赖:
# 云信SDK
pod 'NIMSDK_LITE'
2.2 头文件导入
在需要使用NIMSDK的文件中导入头文件:
#import <NIMSDK/NIMSDK.h>
2.3 项目结构
YuMi/
├── Appdelegate/
│ ├── AppDelegate.m # 主应用代理
│ └── AppDelegate+ThirdConfig.m # 第三方SDK配置
├── Modules/
│ ├── YMMessage/ # 消息模块
│ │ └── Tool/
│ │ └── CustomAttachmentDecoder # 自定义消息解码器
│ ├── YMTabbar/ # 主界面模块
│ └── YMRoom/ # 房间模块
└── Global/
└── YUMIConstant.h # 常量定义
3. NIMSDK初始化流程
3.1 初始化时序图
sequenceDiagram
participant App as AppDelegate
participant ThirdConfig as AppDelegate+ThirdConfig
participant NIMSDK as NIMSDK
participant Config as NIMSDKConfig
participant Decoder as CustomAttachmentDecoder
App->>ThirdConfig: initThirdConfig()
ThirdConfig->>ThirdConfig: configNIMSDK()
ThirdConfig->>NIMSDK: registerWithOption(option)
ThirdConfig->>Decoder: registerCustomDecoder()
ThirdConfig->>Config: shouldConsiderRevokedMessageUnreadCount = YES
ThirdConfig->>Config: setShouldSyncStickTopSessionInfos(YES)
ThirdConfig->>Config: enabledHttpsForInfo = NO (DEBUG)
ThirdConfig->>Config: enabledHttpsForMessage = NO (DEBUG)
Note over App: 应用启动完成
App->>App: loadMainPage()
App->>App: 检查登录状态
App->>NIMSDK: 自动登录或手动登录
3.2 初始化代码实现
3.2.1 主应用代理初始化
// AppDelegate.m
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 初始化第三方SDK配置
[self initThirdConfig];
// 其他初始化代码...
return YES;
}
3.2.2 NIMSDK配置方法
// AppDelegate+ThirdConfig.m
- (void)configNIMSDK {
// 1. 获取云信AppKey
NSString *appKey = KeyWithType(KeyType_NetEase);
NIMSDKOption *option = [NIMSDKOption optionWithAppKey:appKey];
// 2. 配置APNS证书名称
#ifdef DEBUG
option.apnsCername = @"pikoDevelopPush";
#else
option.apnsCername = @"newPiko";
#endif
// 3. 注册SDK
[[NIMSDK sharedSDK] registerWithOption:option];
// 4. 注册自定义消息解码器
[NIMCustomObject registerCustomDecoder:[[CustomAttachmentDecoder alloc] init]];
// 5. 配置SDK参数
[NIMSDKConfig sharedConfig].shouldConsiderRevokedMessageUnreadCount = YES;
[[NIMSDKConfig sharedConfig] setShouldSyncStickTopSessionInfos:YES];
// 6. DEBUG模式下禁用HTTPS
#ifdef DEBUG
[NIMSDKConfig sharedConfig].enabledHttpsForInfo = NO;
[NIMSDKConfig sharedConfig].enabledHttpsForMessage = NO;
#endif
}
4. 关键配置参数说明
4.1 AppKey配置
项目支持多环境配置,通过YUMIConstant.m
中的KeyWithType
方法获取:
// 测试环境
@(KeyType_NetEase): @"79bc37000f4018a2a24ea9dc6ca08d32"
// 生产环境
@(KeyType_NetEase): @"7371d729710cd6ce3a50163b956b5eb6"
4.2 APNS推送配置
// 开发环境
option.apnsCername = @"pikoDevelopPush";
// 生产环境
option.apnsCername = @"newPiko";
4.3 SDK配置参数详解
参数 | 值 | 说明 |
---|---|---|
shouldConsiderRevokedMessageUnreadCount |
YES |
撤回消息计入未读数 |
shouldSyncStickTopSessionInfos |
YES |
同步置顶会话信息 |
enabledHttpsForInfo |
NO (DEBUG) |
DEBUG模式禁用HTTPS信息传输 |
enabledHttpsForMessage |
NO (DEBUG) |
DEBUG模式禁用HTTPS消息传输 |
5. 自定义消息处理
5.1 自定义附件解码器
5.1.1 解码器接口定义
// CustomAttachmentDecoder.h
@interface CustomAttachmentDecoder : NSObject<NIMCustomAttachmentCoding>
@end
5.1.2 解码器实现
// 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;
}
5.2 消息类型定义
自定义消息通过AttachmentModel
定义结构:
@interface AttachmentModel : NSObject<NIMCustomAttachment>
@property (nonatomic, assign) short first; // 消息类型标识
@property (nonatomic, assign) short second; // 消息子类型标识
@property (nonatomic, strong) id data; // 消息数据内容
@end
5.3 消息类型示例
// 打招呼消息
if (attachment.first == CustomMessageType_FindNew &&
attachment.second == Custom_Message_Find_New_Greet_New_User) {
// 处理新用户打招呼消息
FindNewGreetMessageModel *greetInfo = [FindNewGreetMessageModel modelWithDictionary:attachment.data];
// 显示打招呼弹窗
}
6. 登录管理
6.1 登录状态检查
// 检查是否已登录
if ([NIMSDK sharedSDK].loginManager.isLogined) {
// 已登录,执行相关操作
} else {
// 未登录,跳转登录页面
}
6.2 自动登录处理
// NIMLoginManagerDelegate
- (void)onAutoLoginFailed:(NSError *)error {
// 如果非上次登录设备 autoLogin 会返回 417
if (error.code == 417) {
@weakify(self);
AccountModel* accountModel = [AccountInfoStorage instance].getCurrentAccountInfo;
[[NIMSDK sharedSDK].loginManager login:accountModel.uid
token:accountModel.netEaseToken
completion:^(NSError * _Nullable error) {
if (error) {
@strongify(self);
[self.presenter logout];
}
}];
return;
}
[self.presenter logout];
}
6.3 踢出处理
// NIMLoginManagerDelegate
- (void)onKickout:(NIMLoginKickoutResult *)result {
// 显示踢出提示
[XNDJTDDLoadingTool showErrorWithMessage:YMLocalizedString(@"TabbarViewController0")];
// 清理房间状态
if ([XPRoomMiniManager shareManager].getRoomInfo) {
[[RtcManager instance] exitRoom];
[[NIMSDK sharedSDK].chatroomManager exitChatroom:roomId completion:nil];
[self.roomMineView hiddenRoomMiniView];
}
// 执行登出
[self.presenter logout];
}
6.4 手动登录
// 执行登录
[[NIMSDK sharedSDK].loginManager login:accountModel.uid
token:accountModel.netEaseToken
completion:^(NSError * _Nullable error) {
if (error) {
// 登录失败处理
NSLog(@"登录失败: %@", error);
} else {
// 登录成功处理
NSLog(@"登录成功");
}
}];
7. 消息接收处理
7.1 消息接收代理
// NIMChatManagerDelegate
- (void)onRecvMessages:(NSArray<NIMMessage *> *)messages {
if ([AccountInfoStorage instance].getTicket.length == 0) {
return;
}
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;
// 处理自定义消息
[self handleCustomMessage:attachment];
}
}
}
}
}
7.2 自定义消息处理
- (void)handleCustomMessage:(AttachmentModel *)attachment {
switch (attachment.first) {
case CustomMessageType_FindNew:
[self handleFindNewMessage:attachment];
break;
case CustomMessageType_Gift:
[self handleGiftMessage:attachment];
break;
default:
break;
}
}
- (void)handleFindNewMessage:(AttachmentModel *)attachment {
if (attachment.second == Custom_Message_Find_New_Greet_New_User) {
FindNewGreetMessageModel *greetInfo = [FindNewGreetMessageModel modelWithDictionary:attachment.data];
if (greetInfo.uid.integerValue != [AccountInfoStorage instance].getUid.integerValue) {
// 显示打招呼弹窗
[self showGreetAlert:greetInfo];
}
}
}
7.3 广播消息处理
// NIMBroadcastManagerDelegate
- (void)onReceiveBroadcastMessage:(NIMBroadcastMessage *)broadcastMessage {
if ([AccountInfoStorage instance].getUid.length == 0) {
return;
}
// 处理广播消息
NSString *content = broadcastMessage.content;
// 解析并处理广播内容
}
8. 推送通知集成
8.1 推送权限申请
- (void)registerNot {
if (@available(iOS 10.0, *)) {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert |
UNAuthorizationOptionBadge |
UNAuthorizationOptionSound)
completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
if (settings.authorizationStatus == UNAuthorizationStatusAuthorized) {
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] registerForRemoteNotifications];
});
}
}];
}
}];
}
}
8.2 设备Token更新
- (void)application:(UIApplication *)app
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// 上传devicetoken至云信服务器
[[NIMSDK sharedSDK] updateApnsToken:deviceToken];
}
8.3 推送消息处理
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
NSString *data = userInfo[@"data"];
if (data) {
NSDictionary *dataDic = [data mj_JSONObject];
NSString *userId = dataDic[@"uid"];
if (userId) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:kOpenRoomNotification
object:nil
userInfo:@{@"type": @"kOpenChat",
@"uid": userId,
@"isNoAttention": @(YES)}];
ClientConfig *config = [ClientConfig shareConfig];
config.pushChatId = userId;
});
return;
}
}
completionHandler(UIBackgroundFetchResultNewData);
}
8.4 应用状态处理
- (void)applicationDidEnterBackground:(UIApplication *)application {
// 设置应用角标为未读消息数
NSInteger count = [NIMSDK sharedSDK].conversationManager.allUnreadCount;
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:count];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// 应用激活时清除角标
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
[[NSNotificationCenter defaultCenter] postNotificationName:@"kAppDidBecomeActive" object:nil];
}
9. 最佳实践
9.1 初始化最佳实践
- 在应用启动时初始化: 在
AppDelegate
的didFinishLaunchingWithOptions
中调用 - 配置环境参数: 区分开发和生产环境的配置
- 注册自定义解码器: 在SDK注册后立即注册自定义解码器
- 设置代理: 在适当的时机添加和移除代理
9.2 登录管理最佳实践
- 自动登录: 优先使用自动登录,减少用户等待时间
- 错误处理: 对登录失败进行适当的错误处理和重试
- 状态同步: 保持本地登录状态与服务器状态同步
- 踢出处理: 妥善处理被踢出的情况,清理相关状态
9.3 消息处理最佳实践
- 消息过滤: 根据业务需求过滤不需要的消息
- 自定义消息: 合理设计自定义消息结构
- 性能优化: 避免在消息处理中进行耗时操作
- 内存管理: 及时释放不需要的消息对象
9.4 推送通知最佳实践
- 权限申请: 在合适的时机申请推送权限
- Token更新: 及时更新设备Token
- 消息解析: 正确解析推送消息内容
- 状态处理: 根据应用状态处理推送消息
10. 常见问题
10.1 初始化问题
Q: SDK初始化失败怎么办? A: 检查AppKey是否正确,网络连接是否正常,证书配置是否正确。
Q: 自定义解码器注册失败? A: 确保在SDK注册后注册解码器,解码器类实现了正确的协议。
10.2 登录问题
Q: 自动登录失败,错误码417? A: 这是正常情况,表示非上次登录设备,需要重新输入账号密码登录。
Q: 登录后立即被踢出? A: 检查账号是否在其他设备登录,或者Token是否过期。
10.3 消息问题
Q: 自定义消息无法解析? A: 检查消息格式是否正确,解码器是否正确注册。
Q: 消息发送失败? A: 检查网络连接,登录状态,以及消息内容格式。
10.4 推送问题
Q: 推送通知无法接收? A: 检查推送权限是否开启,证书配置是否正确,设备Token是否正确上传。
Q: 推送消息解析错误? A: 检查推送消息格式,确保解析逻辑正确。
11. 总结
本项目对NIMSDK的集成非常完整,包括:
- 完整的初始化流程: 从SDK注册到配置参数设置
- 自定义消息处理: 实现了自定义附件解码器
- 登录状态管理: 包含自动登录、踢出处理等
- 推送通知集成: 完整的APNS推送处理
- 消息接收处理: 支持自定义消息类型的处理
- 多环境配置: 区分开发和生产环境的配置
整个集成方案遵循了NIMSDK的最佳实践,代码结构清晰,功能完整,为项目的即时通讯功能提供了坚实的基础。
文档版本: 1.0
最后更新: 2024年12月
维护人员: 开发团队