Files
peko-ios/docs/NIMSDKManager_Usage_Guide.md

17 KiB
Raw Blame History

NIMSDKManager 使用指南

目录

1. 概述

NIMSDKManager 是一个专门用于管理NIMSDK事务的统一管理类提供了配置、初始化、登录/登出等完整的功能封装。该类采用单例模式设计支持Objective-C和Swift项目使用。

1.1 主要功能

  • 配置管理: 统一的NIMSDK配置管理
  • 初始化: 简化的SDK初始化流程
  • 登录管理: 登录、自动登录、登出等功能
  • 状态监控: 实时监控登录状态变化
  • 消息处理: 消息发送、接收、广播等
  • 推送管理: APNS推送相关功能
  • 代理管理: 支持多代理监听

1.2 设计特点

  • 单例模式: 全局统一管理
  • 代理模式: 支持多代理监听
  • Block回调: 支持异步操作回调
  • Swift兼容: 完美支持Swift项目桥接
  • 错误处理: 完善的错误处理机制

2. Objective-C 使用示例

2.1 基本配置和初始化

// 1. 创建配置模型
NIMSDKConfigModel *config = [[NIMSDKConfigModel alloc] init];
config.appKey = KeyWithType(KeyType_NetEase);
config.apnsCername = @"pikoDevelopPush"; // DEBUG环境
config.shouldConsiderRevokedMessageUnreadCount = YES;
config.shouldSyncStickTopSessionInfos = YES;
config.enabledHttpsForInfo = NO; // DEBUG环境
config.enabledHttpsForMessage = NO; // DEBUG环境

// 2. 配置并初始化
[[NIMSDKManager sharedManager] configureWithConfig:config];
[[NIMSDKManager sharedManager] initializeWithCompletion:^(NSError * _Nullable error) {
    if (error) {
        NSLog(@"NIMSDK初始化失败: %@", error);
    } else {
        NSLog(@"NIMSDK初始化成功");
    }
}];

2.2 登录管理

// 1. 设置登录状态变化监听
[[NIMSDKManager sharedManager] setLoginStatusChangeBlock:^(NIMSDKLoginStatus status) {
    switch (status) {
        case NIMSDKLoginStatusNotLogin:
            NSLog(@"未登录");
            break;
        case NIMSDKLoginStatusLogging:
            NSLog(@"登录中");
            break;
        case NIMSDKLoginStatusLogined:
            NSLog(@"已登录");
            break;
        case NIMSDKLoginStatusLogout:
            NSLog(@"已登出");
            break;
        case NIMSDKLoginStatusKickout:
            NSLog(@"被踢出");
            break;
        case NIMSDKLoginStatusAutoLoginFailed:
            NSLog(@"自动登录失败");
            break;
    }
}];

// 2. 执行登录
[[NIMSDKManager sharedManager] loginWithAccount:@"user123" 
                                          token:@"token123" 
                                     completion:^(NSError * _Nullable error) {
    if (error) {
        NSLog(@"登录失败: %@", error);
    } else {
        NSLog(@"登录成功");
    }
}];

// 3. 自动登录
NSDictionary *autoLoginData = @{@"account": @"user123", @"token": @"token123"};
[[NIMSDKManager sharedManager] autoLoginWithData:autoLoginData 
                                      completion:^(NSError * _Nullable error) {
    if (error) {
        NSLog(@"自动登录失败: %@", error);
    } else {
        NSLog(@"自动登录成功");
    }
}];

// 4. 登出
[[NIMSDKManager sharedManager] logoutWithCompletion:^(NSError * _Nullable error) {
    if (error) {
        NSLog(@"登出失败: %@", error);
    } else {
        NSLog(@"登出成功");
    }
}];

2.3 代理监听

@interface MyViewController () <NIMSDKManagerDelegate>
@end

@implementation MyViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 添加代理
    [[NIMSDKManager sharedManager] addDelegate:self];
}

- (void)dealloc {
    // 移除代理
    [[NIMSDKManager sharedManager] removeDelegate:self];
}

#pragma mark - NIMSDKManagerDelegate

- (void)nimSDKManager:(id)manager didChangeLoginStatus:(NIMSDKLoginStatus)status {
    NSLog(@"登录状态变化: %ld", (long)status);
}

- (void)nimSDKManager:(id)manager didAutoLoginFailed:(NSError *)error {
    NSLog(@"自动登录失败: %@", error);
}

- (void)nimSDKManager:(id)manager didKickout:(NIMLoginKickoutResult *)result {
    NSLog(@"被踢出: %@", result);
}

- (void)nimSDKManager:(id)manager didReceiveMessages:(NSArray<NIMMessage *> *)messages {
    NSLog(@"收到消息: %@", messages);
}

- (void)nimSDKManager:(id)manager didReceiveBroadcastMessage:(NIMBroadcastMessage *)broadcastMessage {
    NSLog(@"收到广播消息: %@", broadcastMessage);
}

@end

2.4 消息管理

// 1. 创建消息
NIMMessage *textMessage = [[NIMSDKManager sharedManager] createTextMessage:@"Hello World"];

// 2. 创建自定义消息
AttachmentModel *attachment = [[AttachmentModel alloc] init];
attachment.first = CustomMessageType_Gift;
attachment.second = Custom_Message_Sub_Gift_Send;
attachment.data = @{@"giftId": @"123", @"giftName": @"玫瑰花"};

NIMMessage *customMessage = [[NIMSDKManager sharedManager] createCustomMessageWithAttachment:attachment];

// 3. 发送消息
NIMSession *session = [NIMSession session:@"receiverId" type:NIMSessionTypeP2P];
[[NIMSDKManager sharedManager] sendMessage:textMessage 
                                 toSession:session 
                                completion:^(NSError * _Nullable error) {
    if (error) {
        NSLog(@"发送失败: %@", error);
    } else {
        NSLog(@"发送成功");
    }
}];

// 4. 获取未读消息数
NSInteger unreadCount = [[NIMSDKManager sharedManager] unreadMessageCount];
NSLog(@"未读消息数: %ld", (long)unreadCount);

// 5. 获取所有会话
NSArray<NIMRecentSession *> *sessions = [[NIMSDKManager sharedManager] allRecentSessions];
NSLog(@"会话数量: %lu", (unsigned long)sessions.count);

2.5 推送管理

// 1. 更新APNS设备Token
- (void)application:(UIApplication *)app 
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    [[NIMSDKManager sharedManager] updateApnsToken:deviceToken];
}

// 2. 处理推送消息
- (void)application:(UIApplication *)application 
didReceiveRemoteNotification:(NSDictionary *)userInfo 
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    
    BOOL handled = [[NIMSDKManager sharedManager] handlePushNotification:userInfo];
    if (handled) {
        completionHandler(UIBackgroundFetchResultNewData);
    } else {
        completionHandler(UIBackgroundFetchResultNoData);
    }
}

3. Swift 桥接使用示例

3.1 创建桥接头文件

在Swift项目中创建桥接头文件 YourProject-Bridging-Header.h

//
//  YourProject-Bridging-Header.h
//  YourProject
//

#ifndef YourProject_Bridging_Header_h
#define YourProject_Bridging_Header_h

#import "NIMSDKManager.h"
#import "AttachmentModel.h"
#import "CustomAttachmentDecoder.h"

#endif /* YourProject_Bridging_Header_h */

3.2 Swift 使用示例

import Foundation
import UIKit

class NIMSDKService {
    
    static let shared = NIMSDKService()
    private let nimManager = NIMSDKManager.shared()
    
    private init() {
        setupNIMSDK()
    }
    
    // MARK: - 配置和初始化
    
    private func setupNIMSDK() {
        // 创建配置
        let config = NIMSDKConfigModel()
        config.appKey = KeyWithType(KeyType_NetEase)
        config.apnsCername = "pikoDevelopPush" // DEBUG环境
        config.shouldConsiderRevokedMessageUnreadCount = true
        config.shouldSyncStickTopSessionInfos = true
        config.enabledHttpsForInfo = false // DEBUG环境
        config.enabledHttpsForMessage = false // DEBUG环境
        
        // 配置并初始化
        nimManager.configure(with: config)
        nimManager.initialize { [weak self] error in
            if let error = error {
                print("NIMSDK初始化失败: \(error)")
            } else {
                print("NIMSDK初始化成功")
                self?.setupDelegates()
            }
        }
    }
    
    private func setupDelegates() {
        // 设置登录状态变化监听
        nimManager.setLoginStatusChangeBlock { [weak self] status in
            self?.handleLoginStatusChange(status)
        }
    }
    
    // MARK: - 登录管理
    
    func login(account: String, token: String, completion: @escaping (Error?) -> Void) {
        nimManager.login(withAccount: account, token: token) { error in
            DispatchQueue.main.async {
                completion(error)
            }
        }
    }
    
    func autoLogin(data: [String: Any], completion: @escaping (Error?) -> Void) {
        nimManager.autoLogin(with: data) { error in
            DispatchQueue.main.async {
                completion(error)
            }
        }
    }
    
    func logout(completion: @escaping (Error?) -> Void) {
        nimManager.logout { error in
            DispatchQueue.main.async {
                completion(error)
            }
        }
    }
    
    // MARK: - 状态查询
    
    var isLogined: Bool {
        return nimManager.isLogined()
    }
    
    var currentAccount: String? {
        return nimManager.currentAccount()
    }
    
    var loginStatus: NIMSDKLoginStatus {
        return nimManager.currentLoginStatus()
    }
    
    // MARK: - 消息管理
    
    func sendTextMessage(_ text: String, to sessionId: String, completion: @escaping (Error?) -> Void) {
        let message = nimManager.createTextMessage(text)
        let session = NIMSession(session: sessionId, type: .p2P)
        
        nimManager.send(message, to: session) { error in
            DispatchQueue.main.async {
                completion(error)
            }
        }
    }
    
    func sendCustomMessage(attachment: NIMCustomAttachment, to sessionId: String, completion: @escaping (Error?) -> Void) {
        let message = nimManager.createCustomMessage(with: attachment)
        let session = NIMSession(session: sessionId, type: .p2P)
        
        nimManager.send(message, to: session) { error in
            DispatchQueue.main.async {
                completion(error)
            }
        }
    }
    
    var unreadMessageCount: Int {
        return Int(nimManager.unreadMessageCount())
    }
    
    var allRecentSessions: [NIMRecentSession] {
        return nimManager.allRecentSessions() ?? []
    }
    
    // MARK: - 推送管理
    
    func updateApnsToken(_ deviceToken: Data) {
        nimManager.updateApnsToken(deviceToken)
    }
    
    func handlePushNotification(_ userInfo: [AnyHashable: Any]) -> Bool {
        return nimManager.handlePushNotification(userInfo)
    }
    
    // MARK: - 私有方法
    
    private func handleLoginStatusChange(_ status: NIMSDKLoginStatus) {
        switch status {
        case .notLogin:
            print("未登录")
        case .logging:
            print("登录中")
        case .logined:
            print("已登录")
        case .logout:
            print("已登出")
        case .kickout:
            print("被踢出")
        case .autoLoginFailed:
            print("自动登录失败")
        @unknown default:
            print("未知状态")
        }
    }
}

// MARK: - Swift 扩展

extension NIMSDKService {
    
    // 创建礼物消息的便捷方法
    func createGiftMessage(giftId: String, giftName: String, giftCount: Int) -> NIMMessage? {
        let attachment = AttachmentModel()
        attachment.first = Int32(CustomMessageType_Gift)
        attachment.second = Int32(Custom_Message_Sub_Gift_Send)
        attachment.data = [
            "giftId": giftId,
            "giftName": giftName,
            "giftCount": giftCount
        ]
        
        return nimManager.createCustomMessage(with: attachment)
    }
    
    // 发送礼物消息的便捷方法
    func sendGift(giftId: String, giftName: String, giftCount: Int, to sessionId: String, completion: @escaping (Error?) -> Void) {
        guard let message = createGiftMessage(giftId: giftId, giftName: giftName, giftCount: giftCount) else {
            completion(NSError(domain: "NIMSDKService", code: -1, userInfo: [NSLocalizedDescriptionKey: "创建礼物消息失败"]))
            return
        }
        
        let session = NIMSession(session: sessionId, type: .p2P)
        nimManager.send(message, to: session) { error in
            DispatchQueue.main.async {
                completion(error)
            }
        }
    }
}

3.3 Swift 视图控制器使用示例

import UIKit

class ChatViewController: UIViewController {
    
    private let nimService = NIMSDKService.shared
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupNIMSDK()
    }
    
    private func setupNIMSDK() {
        // 检查登录状态
        if !nimService.isLogined {
            // 执行登录
            nimService.login(account: "user123", token: "token123") { [weak self] error in
                if let error = error {
                    print("登录失败: \(error)")
                } else {
                    print("登录成功")
                    self?.startChat()
                }
            }
        } else {
            startChat()
        }
    }
    
    private func startChat() {
        // 开始聊天功能
        print("开始聊天")
    }
    
    // MARK: - 发送消息示例
    
    @IBAction func sendTextMessage(_ sender: UIButton) {
        nimService.sendTextMessage("Hello from Swift!", to: "receiver123") { error in
            if let error = error {
                print("发送失败: \(error)")
            } else {
                print("发送成功")
            }
        }
    }
    
    @IBAction func sendGiftMessage(_ sender: UIButton) {
        nimService.sendGift(giftId: "123", giftName: "玫瑰花", giftCount: 1, to: "receiver123") { error in
            if let error = error {
                print("发送礼物失败: \(error)")
            } else {
                print("发送礼物成功")
            }
        }
    }
    
    // MARK: - 获取消息信息
    
    func updateUnreadCount() {
        let count = nimService.unreadMessageCount
        print("未读消息数: \(count)")
    }
    
    func loadRecentSessions() {
        let sessions = nimService.allRecentSessions
        print("会话数量: \(sessions.count)")
    }
}

3.4 Swift AppDelegate 集成

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    var window: UIWindow?
    private let nimService = NIMSDKService.shared
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // NIMSDK已经在NIMSDKService中初始化
        // 这里可以添加其他初始化代码
        
        return true
    }
    
    // MARK: - 推送处理
    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        nimService.updateApnsToken(deviceToken)
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        
        let handled = nimService.handlePushNotification(userInfo)
        completionHandler(handled ? .newData : .noData)
    }
}

4. 配置说明

4.1 环境配置

// DEBUG环境配置
#ifdef DEBUG
    config.apnsCername = @"pikoDevelopPush";
    config.enabledHttpsForInfo = NO;
    config.enabledHttpsForMessage = NO;
#else
    config.apnsCername = @"newPiko";
    config.enabledHttpsForInfo = YES;
    config.enabledHttpsForMessage = YES;
#endif

4.2 AppKey配置

// 从常量文件获取AppKey
config.appKey = KeyWithType(KeyType_NetEase);

// 或者直接设置
config.appKey = @"your_app_key_here";

4.3 推送配置

确保在项目中正确配置了APNS证书并在配置中设置正确的证书名称。

5. 最佳实践

5.1 初始化时机

  • 在App启动时尽早初始化NIMSDK
  • 确保在用户登录前完成初始化

5.2 错误处理

  • 对所有异步操作添加错误处理
  • 在UI线程中处理回调结果

5.3 内存管理

  • 及时移除不需要的代理
  • 避免循环引用

5.4 状态管理

  • 监听登录状态变化
  • 根据状态变化更新UI

5.5 Swift集成

  • 使用桥接头文件正确导入Objective-C类
  • 在Swift中创建便捷的包装方法

6. 常见问题

6.1 编译错误

Q: 编译时提示找不到NIMSDK头文件 A: 确保正确导入了NIMSDK框架并在桥接头文件中正确导入。

6.2 初始化失败

Q: NIMSDK初始化失败 A: 检查AppKey是否正确网络连接是否正常。

6.3 登录问题

Q: 登录后立即被踢出 A: 检查账号是否在其他设备登录或者Token是否过期。

6.4 Swift桥接问题

Q: Swift中无法使用NIMSDKManager A: 确保在桥接头文件中正确导入了相关头文件。

6.5 推送问题

Q: 推送通知无法接收 A: 检查APNS证书配置确保设备Token正确上传。


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