概要介绍


网易作为国内最大最早的即时通信开发商之一,从最早的网易泡泡到后来的易信,已经有了超过十五年的通讯技术积累。现在我们整合了这些产品高稳定、高可靠即时通信能力,开发者能以很小的成本将即时通信功能集成到自己的 APP 中。

网易云信 SDK (NIM SDK) 为移动应用提供完善的即时通信功能开发框架,屏蔽其内部复杂细节,对外提供较为简洁的 API 接口,方便第三方应用快速集成即时通信功能。SDK 兼容 iOS 7.0+ ,Demo 兼容 iOS 8.0+ 。

业务介绍

集成方式


NIM SDK 提供两种集成方式:您既可以通过 CocoaPods 自动集成我们的 SDK,也可以通过手动下载 SDK, 然后添加到您的项目中。

我们提供两个下载地址。分别为:

手动集成

自动集成

Podfile 文件中加入

IM 音视频完整版:

  pod 'NIMSDK'

或 IM 精简版

  pod 'NIMSDK_LITE'

安装

  pod install

如果无法安装 SDK 最新版本,运行以下命令更新本地的 CocoaPods 仓库列表

  pod repo update

类库说明

NIM SDK 主要提供了如下类(协议)与方法

类(协议) 描述 说明
NIMSDK SDK的主入口类 提供初始化,注册,内部管理类管理的功能
NIMLoginManager 登录管理类 负责登录,注销和相应的回调收发
NIMChatManager 聊天管理类 负责消息的收发
NIMConversationManager 会话管理类 负责消息,最近会话的管理
NIMTeamManager 群组管理类 负责群组各种操作
NIMMediaManager 媒体管理类 负责多媒体相关的接口,比如语音录制,声音播放
NIMSystemNotificationManager 系统通知管理类 负责系统消息的接收和存储
NIMApnsManager 推送管理类 负责推送的设置和接收
NIMResourceManager 资源管理类 负责文件的上传和下载
NIMUserManager 好友管理类 负责对好友的增删查,以及对其会话的消息设置
NIMChatroomManager 聊天室管理类 负责聊天室状态管理和数据拉取及设置
NIMDocTranscodingManager 文档转码管理类 负责文档转码的查询和删除等

NIMAVChat 主要提供了如下类(协议)与方法

类(协议) 描述 说明
NIMAVChat NIMSDK 的音视频和实时会话扩展 封装了网络通话、实时会话和网络探测等的管理
NIMNetCallManager 音视频网络通话管理类 提供音视频网络通话功能
NIMRTSManager 实时会话管理类 提供数据通道 (TCP/语音通道) 来满足实时会话的需求
NIMRTSConferenceManager 多人实时会话管理类 提供多人数据通道 (TCP) 来满足多人实时会话的需求
NIMAVChatNetDetectManager 音视频网络探测管理类 提供音视频网络状态诊断功能

调用规则

调用方式

所有业务均通过 NIMSDK 单例调用

@interface NIMSDK : NSObject
/**
 *  获取SDK实例
 *
 *  @return NIMSDK实例
 */
+ (instancetype)sharedSDK;
@end

以获取聊天管理类为例:

id<NIMChatManager> chatManager = [[NIMSDK sharedSDK] chatManager];

通知方式

SDK 通过两种方式通知上层 API 调用结果:回调(callback)和委托 (delegate),两种方式都只在主线程触发。

一般回调接口直接反映在对应接口的 completion 参数上,调用时设置即可。而委托则需要开发者在合适时机在对应管理类上进行添加和移除:一般推荐在相应 ViewController 或管理类初始化进行委托注册,在其销毁时进行移除。

例如,开发者需要在在会话页上监听消息的发送结果

@implementation MySessionViewController

- (void)dealloc
{
  ...
    [[NIMSDK sharedSDK].chatManager removeDelegate:self];
  ...
}

- (void)viewDidLoad 
{
  ...
    [[NIMSDK sharedSDK].chatManager addDelegate:self];
  ...
}

#pragma mark - NIMChatManagerDelegate
- (void)sendMessage:(NIMMessage *)message didCompleteWithError:(NSError *)error
{
    //发送结果
}

所有调用错误都会以 NSError 的形式暴露。针对不同场景,我们将错误进行分类,主要分为以下两种错误域和对应错误码

错误域 错误码 说明
NIMLocalErrorDomain NIMLocalErrorCode 本地操作出错导致
NIMRemoteErrorDomain NIMRemoteErrorCode 与服务器交互出错导致

在开发过程中遇到错误情况,可以对照错误域和错误码进行排查,具体定义可以参考 NIMGlobalDefs.h。当然在开发过程中你也可以通过检视 NSError 中 userInfo 对应的错误描述信息定位问题。

初始化


NIMSDK 注册

NIM SDK 通过注册 App Key 来进行初始化。在使用 SDK 任何方法之前,都应该首先调用初始化方法。正常业务情况下,初始化方法有仅只应调用一次。

原型

@interface NIMSDK : NSObject
/**
 *  初始化SDK
 *
 *  @param option  注册选项
 */
- (void)registerWithOption:(NIMSDKOption *)option;
@end

NIMSDKOption 选项参数列表

参数 类型 说明
appKey NSString 云信分配的 App Key
apnsCername NSString 云信 APNs 推送证书名
pkCername NSString 云信 VOIP 推送证书名

AppKey 作为应用的唯一逻辑标识,同一 AppKey 不同 Bundle Id 的应用消息仍可以互通。

CerName 为开发者为推送证书在云信管理后台定义的名字,在使用中,云信服务器会寻找同名推送证书发起苹果推送服务。

目前 CerName 可传 APNs 证书 和 Voip 证书两种,分别对应了参数中 apnsCernamepkCername 两个字段。

如果没有在后台定义推送证书,则参数可传 nil 。

调用示例

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    ...
    //推荐在程序启动的时候初始化 NIMSDK    
    NSString *appKey        = @"your app key";
    NIMSDKOption *option    = [NIMSDKOption optionWithAppKey:appKey];
    option.apnsCername      = @"your APNs cer name";
    option.pkCername        = @"your pushkit cer name";
    [[NIMSDK sharedSDK] registerWithOption:option];
    ...
}

其他配置初始化

NIM SDK 还提供了一些其他额外的初始化配置以供开发者做一些扩展,定义在 NIMSDKConfig.h 中。

NIMSDKConfig 是一个单例,推荐在调用注册接口前配置。

原型

@interface NIMSDKConfig : NSObject

/**
 *  返回配置项实例
 *
 *  @return 配置项
 */
+ (instancetype)sharedConfig;

@end
配置名称 字段 说明
是否在收到消息后自动下载附件 fetchAttachmentAutomaticallyAfterReceiving 在收到图片或视频消息后,默认情况下 SDK 会去主动获取图片的缩略图和视频的第一帧封面,将这个字段设置为 NO,SDK 将不再主动获取,开发者需要在根据业务逻辑手动调用获取附件接口
是否在收到聊天室消息后自动下载附件 fetchAttachmentAutomaticallyAfterReceivingInChatroom 同普通消息下载附件开关说明,默认情况下 SDK 不会去主动获取聊天室消息的附件
是否使用 NSFileProtectionNone 作为云信文件的 NSProtectionKey fileProtectionNone 默认为 NO,只有在上层 APP 开启了 Data Protection 时才起效。设置成 YES 时,云信文件保护属性 为 NSFileProtectionNone ,设置成 NO 时,为 NSFileProtectionCompleteUntilFirstUserAuthentication
是否需要将被撤回的消息计入未读计算考虑 shouldConsiderRevokedMessageUnreadCount  默认为 NO。设置成 YES 的情况下,如果被撤回的消息本地还未读,那么当消息发生撤回时,对应会话的未读计数将减 1 以保持最近会话未读数的一致性。
是否需要多端同步未读数 shouldSyncUnreadCount 默认为 NO。设置成 YES 的情况下,同个账号多端(PC 和 移动端等)将同步未读计数。
自动登录重试次数 maxAutoLoginRetryTimes 即默认情况下,自动登录将无限重试。设置成大于 0 的值后,在没有登录成功前,自动登录将重试最多 maxAutoLoginRetryTimes 次,如果失败,则抛出错误 (NIMLocalErrorCodeAutoLoginRetryLimit)。

登录


在使用 SDK 之前,需要对云信的体系流程有基本的认知,推荐开发者首先阅读这里

手动登录

@protocol NIMLoginManager <NSObject>
/**
 *  登录
 *
 *  @param account    帐号
 *  @param token      令牌 (在后台绑定的登录token)
 *  @param completion 完成回调
 */
- (void)login:(NSString *)account
        token:(NSString *)token
   completion:(NIMLoginHandler)completion;
@end

示例

NSString *account = @"your account";
NSString *token   = @"your token";
[[[NIMSDK sharedSDK] loginManager] login:account
                                   token:token
                              completion:^(NSError *error) {}];

error 为登录错误信息,成功则为 nil。

SDK 不支持直接添加云信用户,请参考这里,在您的应用服务器上使用 Http 接口进行添加。

自动登录

NIM SDK 有两种自动登录的场景:

1.SDK 发起的自动登录:登录完毕后因网络发生切换,断网等情况发生而需要重连,SDK 将自动进行重连重登,无需 APP 干预,也无需调用任何接口。断线重连的具体介绍可请参考这里

2.APP 发起的自动登录:APP 启动时,如果已保存用户名和密码可以选择调用自动登录接口,并立刻打开主界面。此时 APP 可以在无网络,未登录成功的状态下直接访问用户本地数据。此类登录需要调用如下接口:

原型

@protocol NIMLoginManager <NSObject>
/**
 *  自动登录
 *
 *  @param loginData 自动登录参数
 *  @discussion 启动APP如果已经保存了用户帐号和令牌,建议使用这个登录方式,使用这种方式可以在无网络时直接打开会话窗口
 */
- (void)autoLogin:(NIMAutoLoginData *)loginData;
@end

NIMAutoLoginData 参数列表

参数 类型 说明
account NSString 账号
token NSString 令牌(在后台绑定的登录token)
forcedMode BOOL 强制模式开关

NIMAutoLoginData 中的 forcedMode 为强制模式开关。非强制模式下的自动登录,服务器将检查当前登录设备是否为上一次登录设备,如果不是,服务器将拒绝这次自动登录(返回 error code 为 417 的错误);强制模式下的自动登录,服务器将不检查当前登录设备是否为上一次登录设备,安全性较低,但较为便捷。

示例

NIMAutoLoginData *loginData = [[NIMAutoLoginData alloc] init];
loginData.account = account;
loginData.token = token;

[[[NIMSDK sharedSDK] loginManager] autoLogin:loginData];

和手动登录不同,自动登录通过委托通知登录状态。 APP 需要实现如下回调 (手动登录也会收到同样的委托回调)

@protocol NIMLoginManagerDelegate <NSObject>
/**
 *  登录回调
 *
 *  @param step 登录步骤
 *  @discussion 这个回调主要用于客户端UI的刷新
 */
- (void)onLogin:(NIMLoginStep)step
@end

NIMLoginStep 枚举列表

说明
NIMLoginStepLinking 连接服务器
NIMLoginStepLinkOK 连接服务器成功
NIMLoginStepLinkFailed 连接服务器失败
NIMLoginStepLogining 登录
NIMLoginStepLoginOK 登录成功
NIMLoginStepLoginFailed 登录失败
NIMLoginStepSyncing 开始同步数据
NIMLoginStepSyncOK 同步数据完成
NIMLoginStepLoseConnection 连接断开
NIMLoginStepNetChanged 网络切换

一次完整的登录的基本步骤为

- (void)onAutoLoginFailed:(NSError *)error

自动登录除了会触发相应步骤变化回调外,在发生错误时也会触发如上回调。在碰到一些 SDK 无法自动解决的错误时,开发者需要在此回调里做出相应的处理。

举例来说,当前网络状态较差时,容易导致自动登录发生网络超时错误,此时上层无需处理,SDK 会持续有策略地重连。重连详情请参考这里

而一旦发生用户名密码不匹配的错误时,则需要上层做出相应处理:登出并提示用户手动登录或是从自己的应用服务器刷新相应的用户名密码。一些特殊的登录错误将在下文列出,建议在集成时能尽可能考虑相应应对逻辑。

账号信息获取

在手动登录成功后或是使用自动登录后,我们都可以通过如下接口获取用户云信 id:

NSString *userID = [NIMSDK sharedSDK].loginManager.currentAccount;

userID 不为空的情况下,意味着当前 SDK 已经正确打开对应用户资料,后续可以使用其他管理类获取相应的缓存信息,如最近联系人,消息列表等。

特殊错误码介绍

在登录过程中,开发者需要重点关心以下几个错误码 (NIMRemoteErrorDomain):

登出

应用层登出/注销自己的账号时需要调用 SDK 的登出操作,该操作会通知云信服务器进行 APNs 推送信息的解绑操作,避免用户已登出但推送依然发送到当前设备的情况发生。

@protocol NIMLoginManager <NSObject>
- (void)logout:(nullable NIMLoginHandler)completion;
@end

考虑到用户体验,登出的超时时间会比其他请求短一些。上层应用不管登出请求是否成功,UI 表现上都应该做出登出行为。

示例:

[[[NIMSDK sharedSDK] loginManager] logout:^(NSError *error) {
    //jump to login page
}];

如果遇到登出失败,开发者仍然应该跳转到登录界面,登出失败只是云信服务器进行 APNs 推送信息的解绑失败,本地信息仍然是清理成功的,不会影响到正常业务逻辑与消息收发。

多端登录和互踢

当用户在某个客户端登录时,其他没有被踢掉的端会触发回调:

- (void)onMultiLoginClientsChanged;

同时,可以查询当前时间登录的设备列表:

- (NSArray<NIMLoginClient *> *)currentLoginClients;

云信内置踢人策略为:移动端(Android,iOS)互踢,桌面端(PC,Web)互踢,移动端和桌面端共存。

如果当前的互踢策略无法满足业务需求的话,可以联系我们取消内置互踢,根据多端登录的回调和当前的设备列表,判断本设备是否需要被踢出。如果需要踢出,直接调用登出接口并在界面上给出相关提示即可。

被踢的回调

-(void)onKick:(NIMKickReason)code 
   clientType:(NIMLoginClientType)clientType

APP收到被踢回调后需要进行注销并切换到登录界面。

登录与用户信息同步

NIM SDK 的登录一共有大约十个步骤,包括正在连接,连接成功,正在登录等。详见 NIMLoginStep 枚举。其中重要的两个步骤为:登录成功 (NIMLoginStepLoginOK) 和 同步成功 (NIMLoginStepSyncOK)。

NIM SDK 在登录后会同步群信息,离线消息,漫游消息,系统通知等数据。

断线重连机制

SDK 提供了自动断线重连的策略(重新建立与网易云通信服务器的连接并重新登录),所有重连和登录状态都会在上述的 - (void)onLogin:(NIMLoginStep)step 方法中回调。

具体步骤为:

  1. 从上述可知 SDK 会先建立连接,然后发送登录包请求,当登录包请求发生一些特定出错时 (如登录超时或者服务器内部出错) , SDK 会自动断开连接重连并重新登录。需要注意的是,登录出错有次数上限,超过上限后,SDK 就不会再自动重连。会直接把错误抛给上层。

  2. 当网络变化时,如网络断开或者网络类型切换,SDK 会启动立即上报网络变化的状态, 并启动重连定时器,采用特定的策略并根据当前网络状态进行自动重连,上层开发者无须手动调用登录接口。

  3. 当应用从后台切换到前台时,如果应用进程只是被挂起,则 SDK 会自动进行重连和登录;如果应用进程已被杀死,应用会自动调用 application:didFinishLaunchingWithOptions 接口,则需要在这个接口里或者其他恰当时机手动调用登录接口 (这种情况下推荐使用自动登录)。

消息收发


会话和消息

SDK 中用户与同一个对象的聊天信息集合,称为一个会话,用 NIMSession 来表示。会话有单人会话,群组会话,聊天室会话等类型。

原型

@interface NIMSession : NSObject<NSCopying>

/**
 *  会话ID,如果当前session为team,则sessionId为teamId,如果是P2P则为对方帐号
 */
@property (nonatomic,copy,readonly)         NSString *sessionId;

/**
 *  会话类型,当前仅支持P2P,Team和Chatroom
 */
@property (nonatomic,assign,readonly)       NIMSessionType sessionType;


/**
 *  通过id和type构造会话对象
 *
 *  @param sessionId   会话ID
 *  @param sessionType 会话类型
 *
 *  @return 会话对象实例
 */
 + (instancetype)session:(NSString *)sessionId
                   type:(NIMSessionType)sessionType;

@end

属性列表

参数 类型 说明
sessionId NSString 会话的唯一标识, 如果当前 session 为 team 类型, 则 session Id 为team Id ,如果是点对点单聊类型,则为对方帐号
sessionType NIMSessionType 会话的类型,是一个 NSInteger 的枚举,当前仅支持点对点,群聊和聊天室

在使用的时候,不需要去 SDK 获取会话对象,直接根据已有的会话 Id 和 类型构造出即可。

示例:

//p2p
NIMSession *myFriendSession = [NIMSession session:@"friend user id" type:NIMSessionTypeP2P];

//team
NIMSession *teamSession = [NIMSession session:@"team id" type:NIMSessionTypeTeam];

//do something with session

SDK 中用于表示消息的结构为 NIMMessage。消息属于云信即时通讯中最关键最重要的类,它是传递信息的基本模型。

原型

@interface NIMMessage : NSObject

/**
 *  消息类型
 */
@property (nonatomic,assign,readonly)       NIMMessageType messageType;

/**
 *  消息来源
 */
@property (nullable,nonatomic,copy)                  NSString *from;

/**
 *  消息所属会话
 */
@property (nullable,nonatomic,copy,readonly)       NIMSession *session;

/**
 *  消息ID,唯一标识
 */
@property (nonatomic,copy,readonly)         NSString *messageId;

/**
 *  消息文本
 *  @discussion 消息中除 NIMMessageTypeText 和 NIMMessageTypeTip 外,其他消息 text 字段都为 nil
 */
@property (nullable,nonatomic,copy)                  NSString *text;

/**
 *  消息附件内容
 */
@property (nullable,nonatomic,strong)                id<NIMMessageObject> messageObject;


/**
 *  消息设置
 *  @discussion 可以通过这个字段制定当前消息的各种设置,如是否需要计入未读,是否需要多端同步等
 */
@property (nullable,nonatomic,strong)                NIMMessageSetting *setting;

/**
 *  消息反垃圾配置
 *  @discussion 目前仅支持易盾,只有接入了易盾才可以设置这个配置
 */
@property (nullable,nonatomic,strong)                NIMAntiSpamOption *antiSpamOption;


/**
 *  消息推送文案,长度限制200字节
 */
@property (nullable,nonatomic,copy)                  NSString *apnsContent;

/**
 *  消息推送Payload
 *  @discussion 可以通过这个字段定义消息推送Payload,支持字段参考苹果技术文档,长度限制 2K
 */
@property (nullable,nonatomic,copy)                NSDictionary *apnsPayload;

/**
 *  指定成员推送选项
 *  @discussion 通过这个选项进行一些更复杂的推送设定,目前只能在群会话中使用
 */
@property (nullable,nonatomic,strong)                NIMMessageApnsMemberOption *apnsMemberOption;


/**
 *  服务器扩展
 *  @discussion 客户端可以设置这个字段,这个字段将在本地存储且发送至对端,上层需要保证 NSDictionary 可以转换为 JSON,长度限制 4K
 */
@property (nullable,nonatomic,copy)                NSDictionary    *remoteExt;

/**
 *  客户端本地扩展
 *  @discussion 客户端可以设置这个字段,这个字段只在本地存储,不会发送至对端,上层需要保证 NSDictionary 可以转换为 JSON
 */
@property (nullable,nonatomic,copy)                NSDictionary    *localExt;

/**
 *  消息拓展字段
 *  @discussion 服务器下发的消息拓展字段,并不在本地做持久化,目前只有聊天室中的消息才有该字段(NIMMessageChatroomExtension)
 */
@property (nullable,nonatomic,strong)                id messageExt;

/**
 *  消息发送时间
 *  @discussion 本地存储消息可以通过修改时间戳来调整其在会话列表中的位置,发完服务器的消息时间戳将被服务器自动修正
 */
@property (nonatomic,assign)                NSTimeInterval timestamp;

/**
 *  消息投递状态 仅针对发送的消息
 */
@property (nonatomic,assign,readonly)       NIMMessageDeliveryState deliveryState;


/**
 *  消息附件下载状态 仅针对收到的消息
 */
@property (nonatomic,assign,readonly)       NIMMessageAttachmentDownloadState attachmentDownloadState;


/**
 *  是否是收到的消息
 *  @discussion 由于有漫游消息的概念,所以自己发出的消息漫游下来后仍旧是"收到的消息",这个字段用于消息出错是时判断需要重发还是重收
 */
@property (nonatomic,assign,readonly)       BOOL isReceivedMsg;

/**
 *  是否是往外发的消息
 *  @discussion 由于能对自己发消息,所以并不是所有来源是自己的消息都是往外发的消息,这个字段用于判断头像排版位置(是左还是右)。
 */
@property (nonatomic,assign,readonly)       BOOL isOutgoingMsg;

/**
 *  消息是否被播放过
 *  @discussion 修改这个属性,后台会自动更新db中对应的数据
 */
@property (nonatomic,assign)                BOOL isPlayed;


/**
 *  消息是否标记为已删除
 *  @discussion 已删除的消息在获取本地消息列表时会被过滤掉,只有根据messageId获取消息的接口可能会返回已删除消息。
 */
@property (nonatomic,assign,readonly)       BOOL isDeleted;


/**
 *  对端是否已读
 *  @discussion 只有当当前消息为 P2P 消息且 isOutgoingMsg 为 YES 时这个字段才有效,需要对端调用过发送已读回执的接口
 */
@property (nonatomic,assign,readonly)       BOOL isRemoteRead;

/**
 *  消息发送者名字
 *  @discussion 当发送者是自己时,这个值可能为空,这个值表示的是发送者当前的昵称,而不是发送消息时的昵称。聊天室消息里,此字段无效。
 */
@property (nullable,nonatomic,copy,readonly)         NSString *senderName;


/**
 *  发送者客户端类型
 */
@property (nonatomic,assign,readonly)   NIMLoginClientType senderClientType;
@end

属性列表

参数 类型 说明
messageType 消息类型 消息的类型枚举,只读。当构造消息的时候,SDK 会根据传入的 messageObject 自动判断并填入消息类型
from 消息的发送者 为发送者 Id 。当发送消息的时候,SDK 会根据当前登录情况自动填写
session 消息的所属会话 为消息发送到对话的 Id 。当发送的是点对点消息时,此 Id 为接受者 Id;当发送的是群或聊天室消息时,此 Id 为群或聊天室 Id 。
messageId 消息 Id 消息的唯一标识,在初始化后自动生成
text 消息文本 用来做 UI 显示的消息文本,通常情况下,除了文本消息和提醒消息 外,其他消息 text 字段都为 nil
messageObject 消息附件 开发者需要重点关心的属性,附件需要实现 NIMMessageObject 协议。 开发者通过注入不同的消息附件使消息变为不同类型,并附上不同消息类型所需要的信息,如图片数据,地理位置等
setting 消息设置 开发者通过在发送消息前注入一个消息设置对象,可以制定当前消息的各种设置,如是否需要计入未读,是否需要多端同步等
antiSpamOption 反垃圾选项 目前仅支持易盾,只有接入了易盾才可以设置这个配置
apnsContent 推送文案 APNs 推送文案,设置后,手机在后台将会收到相关文案的苹果推送
apnsPayload 消息推送 Payload 可以通过这个字段定义消息推送 Payload , 苹果内置字段目前只支持 sound 字段
apnsContent 推送文案 APNs 推送文案,设置后,手机在后台将会收到相关文案的苹果推送
apnsMemberOption 指定成员推送选项 开发者通过在发送消息前注入这个设置对象,可以进行一些更复杂的推送设定,比如强制推送,部分推送等。目前只能在群会话中使用
remoteExt 服务器扩展 客户端在发送消息前,可以设置这个字段,这个字段将在本地存储且发送至对端,上层需要保证 NSDictionary 可以转换为 JSON
localExt 客户端扩展 客户端可以设置这个字段,这个字段只在本地存储,不会发送至对端,上层需要保证 NSDictionary 可以转换为 JSON。如果在消息发送后设置,需要手动调用存储消息到本地的方法。
messageExt 消息拓展字段 服务器下发的消息拓展字段,不在本地做持久化,目前只有聊天室中的消息才有该字段 (NIMMessageChatroomExtension) 。
timestamp 消息发送时间 本地存储消息可以通过修改时间戳来调整其在会话列表中的位置,发完服务器的消息时间戳将被服务器自动修正。
isReceivedMsg 是否是收到的消息 由于有漫游消息的概念,所以自己发出的消息漫游下来后仍旧是"收到的消息",这个字段用于消息出错是时判断需要重发还是重收。
deliveryState 消息投递状态 仅针对发送的消息,这个字段才有效。
attachmentDownloadState 消息附件下载状态 仅针对收到的消息,这个字段才有效。
isOutgoingMsg 是否是往外发的消息 由于能对自己发消息,所以并不是所有来源是自己的消息都是往外发的消息,这个字段用于判断头像排版位置(是左还是右)。
isPlayed 消息是否被播放过 修改这个属性,SDK 会自动更新 db 中对应的数据。
isDeleted 消息是否标记为已删除 删除消息在本地存储时只会标记删除状态,已删除的消息在获取本地消息列表时会被过滤掉,只有根据 messageId 获取消息的接口可能会返回已删除消息。
isRemoteRead 对端是否已读 只有当当前消息为 P2P 消息且 isOutgoingMsg 为 YES 时这个字段才有效,需要对端调用过发送已读回执的接口。
senderName 消息发送者名字 当发送者是自己时,这个值可能为空,这个值表示的是发送者当前的昵称,而不是发送消息时的昵称。聊天室消息里,此字段无效。
senderClientType 发送者客户端类型 发送者当时所处的客户端种类,种类可能随着 SDK 版本更新增加,上层开发者需考虑新老版本带来的兼容问题。

上述消息的状态属性,推荐只在主线程对这些属性进行读写

目前提供如下几种消息类型,不同的消息类型对应不同的 MessageObject

消息格式 MessageObject
文本消息 nil
图片消息 NIMImageObject
音频消息 NIMAudioObject
视频消息 NIMVideoObject
文件消息 NIMFileObject
地理位置消息 NIMLocationObject
通知消息 NIMNotificationObject
提醒消息 NIMTipObject
自定义消息 NIMCustomObject

消息发送

开发者需要通过 NIMSDK 里的 NIMChatManager 协议进行消息发送

原型

@protocol NIMChatManager <NSObject>
/**
 *  发送消息
 *
 *  @param message 消息
 *  @param session 接受方
 *  @param error   错误 如果在准备发送消息阶段发生错误,这个error会被填充相应的信息
 *
 *  @return 是否调用成功,这里返回的result只是表示当前这个函数调用是否成功,需要后续的回调才能够判断消息是否已经发送至服务器
 */
- (BOOL)sendMessage:(NIMMessage *)message
          toSession:(NIMSession *)session
              error:(NSError * __nullable *)error;
@end

属性列表

参数 类型 说明
message NIMMessage 需要发送的消息,开发者构造出 message 后,需要选择构造对应的 messageObject 注入 (文本消息直接填入 text 即可,无须消息附件注入),即可传入此接口进行发送
session NIMSession 需要发送到的会话
error NSError * 开发者需要自己构造出一个 NSError 对象,并将对象引用传入。如果在准备发送消息阶段发生错误,这个对象会被填充相应的信息。通常为参数检查错误或者登录状态错误,可参考错误码说明定位具体的出错类型

示例:

1.文本消息。

以发送一条文本消息 hello 至好友 Id 为 user 的业务场景进行示例:

// 构造出具体会话
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// 构造出具体消息
NIMMessage *message = [[NIMMessage alloc] init];
message.text        = @"hello";
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

2.图片消息。

附件原型:

@interface NIMImageObject : NSObject<NIMMessageObject>
/**
 *  图片实例对象初始化方法
 *
 *  @param image 要发送的图片
 *
 *  @return 图片实例对象
 */
- (instancetype)initWithImage:(UIImage*)image;

/**
 *  图片实例对象初始化方法
 *
 *  @param filepath 要发送的图片路径
 *
 *  @return 图片实例对象
 */
- (instancetype)initWithFilepath:(NSString *)filepath;


/**
 *  图片实例对象初始化方法
 *
 *  @param data 图片数据
 *  @param extension 推荐使用的图片数据后缀名
 *
 *  @return 图片实例对象
 */
- (instancetype)initWithData:(NSData *)data
                extension:(NSString *)extension;
/**
 *  文件展示名
 */
@property (nullable, nonatomic, copy) NSString *displayName;


/**
 *  图片本地路径
 *  @discussion 目前 SDK 没有提供下载大图的方法,但推荐使用这个地址作为图片下载地址,APP 可以使用自己的下载类或者 SDWebImage 做图片的下载和管理
 */
@property (nullable, nonatomic, copy, readonly) NSString *path;

/**
 *  缩略图本地路径
 */
@property (nullable, nonatomic, copy, readonly) NSString *thumbPath;


/**
 *  图片远程路径
 */
@property (nullable, nonatomic, copy, readonly) NSString *url;

/**
    *  缩略图远程路径
    *  @discussion 仅适用于使用云信上传服务进行上传的资源,否则无效。
    */
@property (nullable, nonatomic, copy, readonly) NSString *thumbUrl;

/**
 *  图片尺寸
 */
@property (nonatomic, assign, readonly) CGSize size;

/**
 *  图片选项
 *  @discussion 仅在发送时且通过 initWithImage: 方式初始化才有效
 */
@property (nullable, nonatomic ,strong) NIMImageOption *option;

/**
 *  文件大小
 */
@property (nonatomic, assign, readonly) long long fileLength;

@end

参数列表

参数 类型 说明
path NSString 图片本地路径,目前 SDK 没有提供下载大图的方法,但推荐使用这个地址作为图片下载地址, APP 可以使用自己的下载类或者 SDWebImage 做图片的下载和管理
thumbPath NSString 缩略图本地路径,缩略图在默认情况下由 SDK 自动下载,如果发现本地不存在缩略图,可手动调用 NIMChatManager 协议中的获取缩略图方法 fetchMessageAttachment:error: 进行下载
url NSString 大图的远程 URL 路径,开发者可通过这个属性自行下载大图
thumbUrl NSString 缩略图远程 URL 路径,仅适用于使用云信上传服务进行上传的资源,否则无效
size NSString 图片尺寸
option NIMImageOption 图片的压缩选项仅在发送时且通过 initWithImage: 方式初始化才有效
fileLength NSString 文件大小

NIMImageOption 图片选项参数列表

参数 类型 说明
compressQuality float 压缩参数默认为 0 ,可传入 0.0 - 1.0 的值,如果值为 0 或者不合法参数时按照 0.5 进行压缩
format NIMImageFormat 图片压缩格式,可选 JPEG 和 PNG 两种。默认为 JPEG

图片消息附件初始化提供三种方式:

以 UIImage 对象初始化

原型

@interface NIMImageObject : NSObject<NIMMessageObject>
/**
 *  图片实例对象初始化方法
 *
 *  @param image 要发送的图片
 *
 *  @return 图片实例对象
 */
- (instancetype)initWithImage:(UIImage*)image;
@end

以图片路径初始化

原型

@interface NIMImageObject : NSObject<NIMMessageObject>
/**
 *  图片实例对象初始化方法
 *
 *  @param filepath 要发送的图片路径
 *
 *  @return 图片实例对象
 */
 - (instancetype)initWithFilepath:(NSString *)filepath;
 @end

以图片数据初始化

原型

@interface NIMImageObject : NSObject<NIMMessageObject>
  /**
   *  图片实例对象初始化方法
   *
   *  @param data 图片数据
   *  @param extension 推荐使用的图片数据后缀名
   *
   *  @return 图片实例对象
   */
- (instancetype)initWithData:(NSData *)data
                   extension:(NSString *)extension;
@end

以发送一条图片消息, 数据被 image 引用, 至好友 Id 为 user 的业务场景进行示例:

// 构造出具体会话
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// 获得图片附件对象
NIMImageObject *object = [[NIMImageObject alloc] initWithImage:image];
// 构造出具体消息并注入附件
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

以发送一条图片消息, 数据在路径 path 中, 至好友 Id 为 user 的业务场景进行示例:

// 构造出具体会话
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// 获得图片附件对象
NIMImageObject *object = [[NIMImageObject alloc] initWithFilepath:path];
// 构造出具体消息并注入附件
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

以发送一条图片消息, 数据被 image 引用, 至好友 Id 为 user 的业务场景进行示例:

// 构造出具体会话
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// 获得图片附件对象
NIMImageObject *object = [[NIMImageObject alloc] initWithImage:image];
// 构造出具体消息并注入附件
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

以发送一条图片消息, 数据在路径 path 中, 至好友 Id 为 user 的业务场景进行示例:

// 构造出具体会话
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// 获得图片附件对象
NIMImageObject *object = [[NIMImageObject alloc] initWithFilepath:path];
// 构造出具体消息并注入附件
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

以发送一条图片消息, 数据以 NSData 形式 data 引用, 至好友 Id 为 user 的业务场景进行示例:

// 构造出具体会话
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// 获得图片附件对象
NIMImageObject *object = [[NIMImageObject alloc] initWithData:data extension:@"png"];
// 构造出具体消息并注入附件
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

3.音频消息

附件原型:

@interface NIMAudioObject : NSObject<NIMMessageObject>
/**
 *  语音附件初始化方法
 *
 *  @param sourcePath 语音路径
 *
 *  @return 语音实例对象
 */
- (instancetype)initWithSourcePath:(NSString *)sourcePath;

/**
 *  语音附件初始化方法
 *
 *  @param data 语音数据
 *  @param extension 语音数据文件后缀名
 *
 *  @return 语音实例对象
 */
- (instancetype)initWithData:(NSData *)data
                extension:(NSString *)extension;

/**
 *  语音的本地路径
 */
@property (nullable, nonatomic, copy, readonly) NSString *path;

/**
 *  语音的远程路径
 */
@property (nullable, nonatomic, copy, readonly) NSString *url;

/**
 *  语音时长,毫秒为单位
 *  @discussion SDK会根据传入文件信息自动解析出duration,但上层也可以自己设置这个值
 */
@property (nonatomic, assign)  NSInteger duration;

@end

参数列表

参数 类型 说明
path NSString 语音本地路径,语音在默认情况下由 SDK 自动下载,如果发现本地不存在语音文件,可手动调用 NIMChatManager 协议中的获取语音附件方法 fetchMessageAttachment:error: 进行下载
url NSString 语音的远程 URL 路径
duration NSInteger 语音时长,毫秒为单位,SDK会根据传入文件信息自动解析出音频的 duration, 开发者也可以自己计算设置这个值

语音消息附件初始化提供三种方式:

以语音路径初始化

原型

@interface NIMAudioObject : NSObject<NIMMessageObject>
/**
 *  语音附件初始化方法
 *
 *  @param sourcePath 语音路径
 *
 *  @return 语音实例对象
 */
 - (instancetype)initWithSourcePath:(NSString *)sourcePath;
@end

以语音数据初始化

原型

@interface NIMAudioObject : NSObject<NIMMessageObject>
/**
 *  语音对象初始化方法
 *
 *  @param data 语音数据
 *  @param extension 语音数据文件后缀名
 *
 *  @return 语音实例对象
 */ 
 - (instancetype)initWithData:(NSData *)data
                extension:(NSString *)extension;
@end

以发送一条语音消息, 语音保存在路径 path 中, 至好友 Id 为 user 的业务场景进行示例:

    // 构造出具体会话
    NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
    // 获得语音附件对象
    NIMAudioObject *object = [[NIMAudioObject alloc] initWithSourcePath:path];
    // 构造出具体消息并注入附件
    NIMMessage *message = [[NIMMessage alloc] init];
    message.messageObject = object;
    // 错误反馈对象
    NSError *error = nil;
    // 发送消息
    [[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];
以发送一条语音消息, 语音数据被 `data` 引用, 至好友 Id 为 `user` 的业务场景进行示例:
    // 构造出具体会话
    NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
    // 获得语音附件对象
    NIMAudioObject *audioObject = [[NIMAudioObject alloc] initWithData:data extension:@"aac"];
    // 构造出具体消息并注入附件
    NIMMessage *message = [[NIMMessage alloc] init];
    message.messageObject = object;
    // 错误反馈对象
    NSError *error = nil;
    // 发送消息
    [[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

4.视频消息

附件原型:

@interface NIMVideoObject : NSObject<NIMMessageObject>

/**
 *  视频实例对象的初始化方法
 *
 *  @param sourcePath 视频的文件路径
 *
 *  @return 视频实例对象
 */
- (instancetype)initWithSourcePath:(NSString *)sourcePath;


/**
 *  视频实例对象的初始化方法
 *
 *  @param data 视频数据
 *  @param extension 视频文件后缀
 *
 *  @return 视频实例对象
 */
- (instancetype)initWithData:(NSData *)data
                extension:(NSString *)extension;

/**
 *  视频展示名
 */
@property (nullable, nonatomic, copy) NSString *displayName;

/**
 *  视频MD5
 */
@property (nullable, nonatomic, copy, readonly) NSString *md5;

/**
 *  视频的本地路径
 *  @discussion 目前 SDK 并不提供视频下载功能,但是建议 APP 使用这个 path 作为视频的下载地址,以便后期 SDK 提供缓存清理等功能
 */
@property (nullable, nonatomic, copy, readonly) NSString *path;

/**
 *  视频的远程路径
 */
@property (nullable, nonatomic, copy, readonly) NSString *url;

/**
 *  视频封面的远程路径
 *  @discussion 只有是上传到云信服务器上的视频才支持封面地址,否则地址无效
 */
@property (nullable, nonatomic, copy, readonly) NSString *coverUrl;

/**
 *  视频封面的本地路径
 */
@property (nullable, nonatomic, copy, readonly) NSString *coverPath;

/**
 *  封面尺寸
 */
@property (nonatomic, assign, readonly) CGSize coverSize;

/**
 *  视频时长,毫秒为单位
 *  @discussion SDK会根据传入文件信息自动解析出duration,但上层也可以自己设置这个值
 */
@property (nonatomic, assign) NSInteger duration;

/**
 *  文件大小
 */
@property (nonatomic, assign, readonly) long long fileLength;

@end

参数列表

参数 类型 说明
displayName NSString 视频的显示名, 由开发者自行定义,供上层 UI 使用
md5 NSString 根据视频数据生成的 MD5
path NSString 视频的本地路径。目前 SDK 并不提供视频下载功能,但是建议 APP 使用这个 path 作为视频的下载地址,以便后期 SDK 提供缓存清理等功能
url NSString 视频的远程路径
coverUrl NSString 视频封面的远程路径,只有是上传到云信服务器上的视频才支持封面地址,否则地址无效
coverPath NSString 视频封面的本地路径。视频封面在默认情况下由 SDK 自动下载,如果发现本地不存在封面文件,可手动调用 NIMChatManager 协议中的获取封面方法 fetchMessageAttachment:error: 进行下载
coverSize CGSize 视频封面的大小,由 SDK 自行计算
duration NSInteger 视频时长,毫秒为单位, SDK 会根据传入文件信息自动解析出 duration ,但上层也可以自己设置这个值

视频消息附件初始化提供两种方式:

以路径初始化

原型

@interface NIMVideoObject : NSObject<NIMMessageObject>
/**
 *  视频实例对象的初始化方法
 *
 *  @param sourcePath 视频的文件路径
 *
 *  @return 视频实例对象
 */
- (instancetype)initWithSourcePath:(NSString *)sourcePath;
@end

以数据对象初始化

原型

@interface NIMVideoObject : NSObject<NIMMessageObject>
/**
 *  视频实例对象的初始化方法
 *
 *  @param data 视频数据
 *  @param extension 视频文件后缀
 *
 *  @return 视频实例对象
 */
- (instancetype)initWithData:(NSData *)data
                extension:(NSString *)extension;
@end

以发送一条视频消息, 视频保存在路径 path 中, 至好友 Id 为 user 的业务场景进行示例:

// 构造出具体会话
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// 获得视频附件对象
NIMVideoObject *object = [[NIMVideoObject alloc] initWithSourcePath:path];
// 构造出具体消息并注入附件
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

以发送一条视频消息, 视频数据被 data 引用, 至好友 Id 为 user 的业务场景进行示例:

// 构造出具体会话
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// 获得视频附件对象
NIMVideoObject *object = [[NIMVideoObject alloc] initWithData:data extension:@"mp4"];
// 构造出具体消息并注入附件
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

5.文件消息

附件原型:

@interface NIMFileObject : NSObject<NIMMessageObject>

/**
 *  文件对象初始化方法(根据文件路径)
 *
 *  @param sourcePath 文件路径
 *
 *  @return 文件实例对象
 */
- (instancetype)initWithSourcePath:(NSString *)sourcePath;


/**
 *  文件对象初始化方法(根据文件数据)
 *
 *  @param data 文件数据
 *  @param extension 文件拓展名
 *  @return 文件实例对象
 */

- (instancetype)initWithData:(NSData*)data extension:(NSString*)extension;


/**
 *  文件显示名
 */
@property (nullable, nonatomic, copy)  NSString *displayName;

/**
 *  文件的本地路径
 */
@property (nullable ,nonatomic, copy, readonly) NSString *path;

/**
 *  文件的远程路径
 */
@property (nullable,nonatomic, copy, readonly) NSString *url;


/**
 *  文件MD5
 */
@property (nullable,nonatomic, copy, readonly) NSString *md5;

/**
 *  文件大小
 */
@property (nonatomic, assign, readonly) long long fileLength;

@end

参数列表

参数 类型 说明
displayName NSString 文件的显示名, 由开发者自行定义,供上层 UI 使用
md5 NSString 根据文件数据生成的 MD5
path NSString 文件的本地路径。目前 SDK 并不提供文件下载功能,但是建议 APP 使用这个 path 作为文件的下载地址,以便后期 SDK 提供缓存清理等功能
url NSString 文件的远程路径
fileLength long long 文件的大小

文件消息附件初始化提供两种方式:

以路径初始化

原型

@interface NIMFileObject : NSObject<NIMMessageObject>
/**
 *  文件对象初始化方法(根据文件路径)
 *
 *  @param sourcePath 文件路径
 *
 *  @return 文件实例对象
 */
 - (instancetype)initWithSourcePath:(NSString *)sourcePath;
@end

以数据对象初始化

原型

@interface NIMFileObject : NSObject<NIMMessageObject>
/**
 *  文件实例对象的初始化方法
 *
 *  @param data 文件数据
 *  @param extension 文件后缀
 *
 *  @return 文件实例对象
 */
- (instancetype)initWithData:(NSData *)data
                    extension:(NSString *)extension;
@end

以发送一条文件消息, 文件保存在路径 path 中, 至好友 Id 为 user 的业务场景进行示例:

// 构造出具体会话
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// 获得文件附件对象
NIMFileObject *object = [[NIMFileObject alloc] initWithSourcePath:path];
// 构造出具体消息并注入附件
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

以发送一条视频消息, 视频数据被 data 引用, 至好友 Id 为 user 的业务场景进行示例:

// 构造出具体会话
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// 获得视频附件对象
NIMFileObject *audioObject = [[NIMFileObject alloc] initWithData:data extension:@"data"];
// 构造出具体消息并注入附件
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

6.位置消息

附件原型:

@interface NIMLocationObject : NSObject<NIMMessageObject>

/**
 *  位置实例对象初始化方法
 *
 *  @param latitude  纬度
 *  @param longitude 经度
 *  @param title   地理位置描述
 *  @return 位置实例对象
 */
- (instancetype)initWithLatitude:(double)latitude
                longitude:(double)longitude
                    title:(nullable NSString *)title;

/**
 *  维度
 */
@property (nonatomic, assign, readonly) double latitude;

/**
 *  经度
 */
@property (nonatomic, assign, readonly) double longitude;

/**
 *  标题
 */
@property (nullable, nonatomic, copy, readonly) NSString *title;
@end
参数列表
参数 类型 说明
latitude double 维度位置,由初始化时传入
longitude double 经度位置,由初始化时传入
title NSString 位置标题信息,由初始化时传入

初始化方法原型

@interface NIMLocationObject : NSObject<NIMMessageObject>
/**
 *  位置实例对象初始化方法
 *
 *  @param latitude  纬度
 *  @param longitude 经度
 *  @param title   地理位置描述
 *  @return 位置实例对象
 */
- (instancetype)initWithLatitude:(double)latitude
                        longitude:(double)longitude
                            title:(nullable NSString *)title;
@end

以发送一条位置消息, 经纬度为 (30.27415,120.15515) ,地点名为 address , 至好友 Id 为 user 的业务场景进行示例:

// 构造出具体会话
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// 获得位置附件对象
NIMLocationObject *object = [[NIMLocationObject alloc] initWithLatitude:120.15515 longitude:30.27415 title:@"address"];
// 构造出具体消息并注入附件
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

以发送一条视频消息, 视频数据被 data 引用, 至好友 Id 为 user 的业务场景进行示例:

// 构造出具体会话
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// 获得视频附件对象
NIMFileObject *audioObject = [[NIMFileObject alloc] initWithData:data extension:@"data"];
// 构造出具体消息并注入附件
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

7.提示消息

提示消息主要用于会话内的通知提醒,消息使用场景例如:进入会话时出现的欢迎消息,或是会话过程中命中敏感词后的提示消息等场景,当然也可以用自定义消息实现,只是相对复杂一些。

提示消息附件内部没有额外的信息字段,提示内容建议放入 NIMMessage 中的 text 字段,额外信息可以存储在 NIMMessageremoteExtlocalExt 字段中。

附件原型:

@interface NIMTipObject : NSObject<NIMMessageObject>
@end

以发送一条提示消息, 文案内容为 welcome , 至好友 Id 为 user 的业务场景进行示例:

// 构造出具体会话
NIMSession *session  = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// 获得文件附件对象
NIMTipObject *object = [[NIMTipObject alloc] init];
// 构造出具体消息并注入附件
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
message.text = @"welcome";
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

8.自定义消息

除了 SDK 预定义的几种消息类型,上层APP开发者如果想要实现更多的消息类型,不可避免需要使用自定义消息这种类型。由于 SDK 并不能预测上层 APP 的应用场景,所以 NIMCustomObject 采取消息透传的方式以提供给上层开发者最大的自由度。

SDK 只负责发送和收取由 NIMCustomObject 中 id attachment 序列化和反序列化后的字节流,在发送端,SDK 获取 encodeAttachment 后得到的字节流发送至对面端;在接收端,SDK 读取字节流,并通过上层 APP 设置的反序列化对象进行解析。

附件原型:

@interface NIMCustomObject : NSObject<NIMMessageObject>

/**
 *  用户自定义附件
 *  @discussion SDK负责将attachment通过encodeAttachment接口序列化后的结果进行透传
 */
@property(nullable, nonatomic, strong) id<NIMCustomAttachment>  attachment;


/**
 *  注册自定义消息解析器
 *
 *  @param decoder 自定义消息解析器
 *  @disucssion 如果用户使用自定义消息类型,就需要注册自定义消息解析器,负责将透传过来的自定义消息反序列化成上层应用可识别的对象
 */
+ (void)registerCustomDecoder:(id<NIMCustomAttachmentCoding>)decoder;

@end

参数列表

参数 类型 说明
attachment id 用户自定义的附件类封装,需要实现NIMCustomAttachment,在发送的时候讲对象赋值到这个属性。SDK负责将 attachment 通过encodeAttachment 接口序列化后的结果进行透传

文件上传托管:

为了方便 APP 在自定义消息类型中进行文件的上传,SDK 也提供了三个接口文件上传 即只要 APP 实现上传相关的接口,资源的上传就可以由 SDK 自动完成

如需要上传资源需要实现的接口有:

文件下载托管雷同:

如需要下载资源需要实现的接口有:

以发送一条自定义消息, 自定义封装在 MyCustomAttach 中 , 至好友 Id 为 user 的业务场景进行示例,同时需要上传和下载托管,分别为 uploadURLdownloadURL:

// MyCustomAttach.h
@interface MyCustomAttach : NSObject<NIMCustomAttachment>
@property (nonatomic,copy) NSString *filePath;

@property (nonatomic,copy) NSString *uploadURL;
@property (nonatomic,copy) NSString *downloadURL;
@end

// MyCustomAttach.m
@implementation MyCustomAttach

// 实现 NIMCustomAttachment
- (NSString *)encodeAttachment
{
    NSDictionary *dict = @{
                            @"path"      :  self.filePath,
                            @"upload"    :  self.uploadURL,
                            @"download"  :  self.downloadURL,
                            };

    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict
                                                    options:0
                                                        error:nil];
    return [[NSString alloc] initWithData:jsonData
                                encoding:NSUTF8StringEncoding];
}

// 上传托管
- (BOOL)attachmentNeedsUpload
{
    // 如果没有拿到上传地址,则需要上传
    return self.uploadURL.length == 0;
}

- (NSString *)attachmentPathForUploading
{
    return self.filePath;
}

- (void)updateAttachmentURL:(NSString *)urlString
{
    self.uploadURL = urlString;
}

// 下载托管
- (BOOL)attachmentNeedsDownload
{
    return ![[NSFileManager defaultManager] fileExistsAtPath:self.filePath];
}

- (NSString *)attachmentURLStringForDownloading
{
    return self.downloadURL;
}

- (NSString *)attachmentPathForDownloading
{
    return self.filePath;
}

@end
// 构造出具体会话
NIMSession *session  = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// 获得文件附件对象
MyCustomAttach *attachment = [[MyCustomAttach alloc] init];
NIMCustomObject *object    = [[NIMCustomObject alloc] init];
object.attachment = attachment;

// 构造出具体消息并注入附件
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;

// 错误反馈对象
NSError *error = nil;
// 发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

9.机器人消息

机器人类型消息分为机器人上行、下行消息,分别表示发送给机器人和机器人下发的消息。客户端构建机器人上行消息并调用发送接口发送机器人消息,在收到机器人下行消息之后通过解析附件中的 response 属性获取机器人具体响应内容。

附件原型:

@interface NIMRobotObject : NSObject<NIMMessageObject>

/**
*  机器人消息附件对象构造方法
* 
*  @param content 机器人识别内容
*
*  @param robotId 机器人 Id
*
*  @discussion content 参数不是用来做 UI 显示的, 显示 (如对话气泡) 请用 message.text 字段
*
*  @return  机器人消息附件对象实例
*/
- (instancetype)initWithRobot:(NSString *)content
                    robotId:(NSString *)robotId;


/**
 *  机器人消息附件对象构造方法
 *
 *  @param robotId  机器人 Id
 *
 *  @param modelId  模块 Id
 *
 *  @param param    模块跳转参数
 *
 *  @return  机器人消息附件对象实例
 */
- (instancetype)initWithRobotId:(NSString *)robotId
                        modelId:(NSString *)modelId
                          param:(NSString *)param;


/**
 *  判断此消息是否是属于机器人回复的消息
 */
@property (nonatomic, assign, readonly) BOOL isFromRobot;

/**
 *  当该消息为用户上行发送给机器人时,此字段为目标机器人 Id,
 *  当该消息为机器人回复的消息时, 此字段为本消息所属机器人 Id
 */
@property (nullable, nonatomic, copy, readonly) NSString *robotId;


/**
 *  机器人回复的消息结果,只在机器人下行消息,此字段有效
 */
@property (nullable, nonatomic, copy, readonly) NSDictionary *response;

/**
 *  机器人回复的消息所属的提问消息 Id ,只在机器人下行消息,此字段有效
 */
@property (nullable, nonatomic, copy, readonly) NSString *responseForMessageId;

@end

参数列表

参数 类型 说明
isFromRobot BOOL 是否是属于机器人回复的消息,用来判断机器人消息的上下行
robotId NSString 当该消息为用户上行发送给机器人时,此字段为目标机器人 Id, 当该消息为机器人回复的消息时, 此字段为本消息所属机器人 Id
response NSDictionary 机器人回复的消息结果,只在机器人下行消息,此字段有效
responseForMessageId NSString 机器人回复的消息所属的提问消息 Id ,只在机器人下行消息,此字段有效

机器人上行消息附件初始化提供两种方式:

通过文本内容与机器人进行对话

原型

@interface NIMRobotObject : NSObject<NIMMessageObject>
/**
 *  机器人消息附件对象构造方法
 * 
 *  @param content 机器人识别内容
 *
 *  @param robotId 机器人 Id
 *
 *  @discussion content 参数不是用来做 UI 显示的, 显示 (如对话气泡) 请用 message.text 字段
 *
 *  @return  机器人消息附件对象实例
 */
- (instancetype)initWithRobot:(NSString *)content
                    robotId:(NSString *)robotId;
@end

通过机器人跳转的模块 Id 初始化

原型

@interface NIMFileObject : NSObject<NIMMessageObject>
/**
 *  机器人消息附件对象构造方法
 *
 *  @param robotId  机器人 Id
 *
 *  @param modelId  模块 Id
 *
 *  @param param    模块跳转参数
 *
 *  @return  机器人消息附件对象实例
 */
- (instancetype)initWithRobotId:(NSString *)robotId
                        modelId:(NSString *)modelId
                        param:(NSString *)param;
@end

以发送一条机器人消息, 对话文本为 hello , 对话机器人 Id 为 robot,到群 Id myTeam 的业务场景进行示例:

// 构造出具体会话
NIMSession *session = [NIMSession session:@"myTeam" type:NIMSessionTypeTeam];
// 获得机器人附件对象
NIMRobotObject *object = [[NIMRobotObject alloc] initWithRobot:@"hello" robotId:@"robot"];
// 构造出具体消息并注入附件
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// 错误反馈对象
NSError *error = nil;
// 发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

10.通知消息

一些特定场景的行为,云信服务器预置了一些通知消息。通知消息也是一种特定消息,开发者需要解析消息中附带的信息,来获取通知内容。

附件原型:

@interface NIMNotificationObject : NSObject<NIMMessageObject>
/**
 *  通知内容
 */
@property (nonatomic,strong,readonly) NIMNotificationContent  *content;

/**
 *  通知类型
 */
@property (nonatomic,assign,readonly) NIMNotificationType notificationType;
@end

参数列表

参数 类型 说明
content NIMNotificationContent 通知内容
notificationType NIMNotificationType 通知类型,通知类型会随着 SDK 版本升级扩展,开发者需要考虑升级所带来的兼容问题

通知消息需要进行解析,具体步骤为:

所有 content 类型如下:

通知类型 NIMNotificationContent
群通知 NIMTeamNotificationContent
网络电话通知 NIMNetCallNotificationContent
聊天室通知 NIMChatroomNotificationContent
未被支持类型通知 NIMUnsupportedNotificationContent

由于系统升级,旧版本的 SDK 可能无法解析新版本数据,所有无法解析的新通知显示为未被支持。

当不需要一些通知时,开发者可以实现 NIMSDKConfig 的委托 delegate,来控制哪些通知需要忽略。具体请参考 初始化 章节

不支持从客户端发出通知消息。

接收消息

收消息过程会通过 chatManager 的回调函数通知上层

原型

@protocol NIMChatManagerDelegate <NSObject>
- (void)onRecvMessages:(NSArray<NIMMessage *> *)messages
@end

参数列表

参数 类型 说明
messages NSArray 消息集合,集合按时间排序并保证所属同一个会话

如果收到的是图片,视频等需要下载附件的消息,在回调的处理中还需要调用下载附件接口

(SDK 默认会在第一次收到消息时自动调用)

原型

@protocol NIMChatManager <NSObject>
- (BOOL)fetchMessageAttachment:(NIMMessage *)message
                         error:(NSError **)error
@end

参数列表

参数 类型 说明
message NIMMessage 需要获取附件的消息
error NSError 抛出的错误对象

进行附件的下载,附件的下载过程会通过回调反馈

下载进度原型

@protocol NIMChatManagerDelegate <NSObject>
- (void)fetchMessageAttachment:(NIMMessage *)message
                      progress:(float)progress
@end

参数列表

参数 类型 说明
message NIMMessage 正在下载附件的消息
progress float 下载进度,范围为 0 ~ 1

下载完成原型

@protocol NIMChatManagerDelegate <NSObject>
- (void)fetchMessageAttachment:(NIMMessage *)message
          didCompleteWithError:(NSError *)error;
@end

参数列表

参数 类型 说明
message NIMMessage 正在下载附件的消息
error NSError 下载出错原因

聊天室接收消息

由于聊天室为消息量较大的场景,在接收消息时,SDK 为了防止过频回调,会在接受到消息包后等待一段时间,然后批量上报收到的消息。

在此同时,由于业务逻辑不一致导致界面处理不同,如果开发者仍然觉得消息插入过频导致界面卡顿,可以考虑在上层做一个带插入的消息池,同时创建专门用来计算排版的子线程。具体逻辑可以参考 Demo 的聊天室消息处理。

消息转发

除了 通知消息 之外,其他类型消息均支持转发给其他会话。

@protocol NIMChatManager <NSObject>
- (BOOL)forwardMessage:(NIMMessage *)message
             toSession:(NIMSession *)session
                 error:(NSError **)error
@end
参数 类型 说明
message NIMMessage 需要转发的消息
session NIMSession 需要转发到的会话
error NSError 出错原因

这里返回的 error 参数只是表示当前这个函数调用是否成功,需要后续的回调才能够判断消息是否已经发送至服务器。后续回调和普通消息发送流程相同。

已读回执

在会话界面中调用发送已读回执的接口并传入最后一条消息,即表示这之前的消息都已读,对端将收到此回执。

发送已读回执

@protocol NIMChatManager <NSObject>
- (void)sendMessageReceipt:(NIMMessageReceipt *)receipt
                completion:(NIMSendMessageReceiptBlock)completion;
@end
参数 类型 说明
receipt NIMMessageReceipt 消息回执
completion NIMSendMessageReceiptBlock 完成回调

接受已读回执

@protocol NIMChatManagerDelegate <NSObject>
- (void)onRecvMessageReceipt:(NIMMessageReceipt *)receipt;
@end

在发送端 NIMMessageReceipt 需要通过最后一条消息 NIMMessage 进行初始化并进行发送,而接收端可以通过 NIMMessageReceipt 中的 timestamp 来得知发送端当前已读时间戳。此功能仅在 P2P 消息中有效。重复发送和通过无效消息构造的已读回执都将被 SDK 忽略。

消息撤回

在会话时,允许用户撤回一定时间内发送过的消息。

@protocol NIMChatManager <NSObject>
- (void)revokeMessage:(NIMMessage *)message
           completion:(NIMRevokeMessageBlock)completion;
@end
参数 类型 说明
message NIMMessage 需要撤回的消息
completion NIMRevokeMessageBlock 完成回调

在撤回消息请求调用成功后, SDK 会先回调给上层成功,再自动将本地的这条消息删除。如果需要在撤回后显示一条已撤回的提示 ( 见 Demo 交互 ) ,开发者可以自行构造一条提醒消息并插入本地数据库。

以下情况消息撤回会失败

当有消息撤回发生时,被撤回方 SDK 会触发回调:

@protocol NIMChatManagerDelegate <NSObject>
- (void)onRecvRevokeMessageNotification:  (NIMRevokeMessageNotification *)notification
@end

SDK 在收到消息撤回后,会先从本地数据库中找到对应消息并进行删除,之后通知上层消息已删除。如果需要在撤回后显示一条已撤回的提示 ( 见 Demo 交互 ) ,开发者在这个回调中自行构造一条提醒消息并插入本地数据库。

由于用户业务场景不一致,在撤回后可能在撤回后用一条提醒消息替代,也有可能不做任何提示,而被撤回的消息本身可能是未读的,这样不同的业务逻辑就造成了未读数的不一致。 在 NIMSDKConfig.h 中统一封装了撤回未读配置,详见 初始化 章节

接口原型

@interface NIMSDKConfig : NSObject
@property (nonatomic,assign) BOOL shouldConsiderRevokedMessageUnreadCount;
@end

最近会话


最近会话概念

最近会话用于表示会话列表页的数据模型。当用户发送,收取及删除消息时,都会同时去修改最近会话。

当收到或者一条消息时,会自动生成这个消息对应的最近会话。但值得注意的是最近会话和会话并不是一一对应的关系,删除最近会话并不会影响会话。

最近会话类与属性

最近会话在 SDK 中用 NIMRecentSession 表示

/**
 *  最近会话
 */
@interface NIMRecentSession : NSObject

/**
 *  当前会话
 */
@property (nullable,nonatomic,readonly,copy)   NIMSession  *session;

/**
 *  最后一条消息
 */
@property (nullable,nonatomic,readonly,strong)   NIMMessage  *lastMessage;

/**
 *  未读消息数,为保证线程安全,请在主线程中获取
 */
@property (nonatomic,readonly,assign)   NSInteger   unreadCount;

/**
 *  本地扩展
 */
@property (nullable,nonatomic,readonly,copy) NSDictionary *localExt;

@end

属性列表

参数 类型 说明
session NIMSession 表示的当前会话
lastMessage NIMMessage 当前会话的最后一条消息
unreadCount NSInteger 未读消息数,为保证线程安全,请在主线程中获取
localExt NSDictionary 最近会话的本地扩展,修改后,需要调用 NIMConversationManagerProtocolupdateRecentLocalExt:recentSession: 方法,才可以存储到本地

NIMConversationManagerProtocol.h 中的 NIMConversationManager 协议用于增删改查本地消息和最近会话, NIMConversationManagerDelegate 协议用于回调通知最近会话的变更,下面会针对具体接口详细论述。

原型

@protocol NIMConversationManager <NSObject>
/**
 *  获取所有最近会话
 *  @discussion 只能在主线程调用
 *  @return 最近会话列表
 */
- (nullable NSArray<NIMRecentSession *> *)allRecentSessions;
@end

为了保证线程安全,这个方法只能在主线程调用,并且由于最近会话在内部是以字典形式存储的,在取出时,会对其进行排序,在数据量过万的情况下会有一定的耗时。

示例

//  NIMSessionListViewController.m
- (void)viewDidLoad {
    ...
    NSArray *recentSessions = [NIMSDK sharedSDK].conversationManager.allRecentSessions;
    ...
}

NIMConversationManagerDelegate 提供了最近会话的三个回调通知上层:

分别为增加,修改,删除最近会话的回调:

@protocol NIMConversationManagerDelegate <NSObject>
/**
 *  增加最近会话的回调
 *
 *  @param recentSession    最近会话
 *  @param totalUnreadCount 目前总未读数
 *  @discussion 当新增一条消息,并且本地不存在该消息所属的会话时,会触发此回调。
 */
- (void)didAddRecentSession:(NIMRecentSession *)recentSession
           totalUnreadCount:(NSInteger)totalUnreadCount;

/**
 *  最近会话修改的回调
 *
 *  @param recentSession    最近会话
 *  @param totalUnreadCount 目前总未读数
 *  @discussion 触发条件包括: 1.当新增一条消息,并且本地存在该消息所属的会话。
 *                          2.所属会话的未读清零。
 *                          3.所属会话的最后一条消息的内容发送变化。(例如成功发送后,修正发送时间为服务器时间)
 *                          4.删除消息,并且删除的消息为当前会话的最后一条消息。
 */
- (void)didUpdateRecentSession:(NIMRecentSession *)recentSession
              totalUnreadCount:(NSInteger)totalUnreadCount;

/**
 *  删除最近会话的回调
 *
 *  @param recentSession    最近会话
 *  @param totalUnreadCount 目前总未读数
 */
- (void)didRemoveRecentSession:(NIMRecentSession *)recentSession
              totalUnreadCount:(NSInteger)totalUnreadCount;

@end

属性列表

参数 类型 说明
recentSession NIMRecentSession 产生变化的最近会话
totalUnreadCount NSInteger 目前总未读数

获取单个 NIMRecentSession 的未读数时,可以通过回调上来的 NIMRecentSessionunreadCount 属性直接获取。

开发者无法自己添加最近消息,最近消息会在发送或者收到消息的时候自动添加,并触发增加最近会话的回调。

可以通过 NIMConversationManager 获取消息的总未读数,注意为了保证线程安全,只能在主线程上调用读取此数据

@protocol NIMConversationManager <NSObject>
/**
 *  获取所有未读数
 *  @discussion 只能在主线程调用,包括忽略提醒的会话
 *  @return 未读数
 */
- (NSInteger)allUnreadCount;
@end

当 SDK 收到消息后,默认消息为未读消息,未读数累加 1 。因为 SDK 是和 UI 完全隔离的,SDK 无法自动感知何时消息已读,故需要上层开发者根据自己的 UI 逻辑,在恰当的时候,手动调用标记已读 接口来告诉 SDK ,从而 SDK 可以进行清除未读数,标记消息状态等之后的维护工作。 相应的最近会话(如果有的话)未读数会自动置 0 并且触发最近消息修改的回调。

原型

@protocol NIMConversationManager <NSObject>
/**
 *  设置一个会话里所有消息置为已读
 *
 *  @param session 需设置的会话
 *  @discussion 异步方法,消息会标记为设置的状态
 */
- (void)markAllMessagesReadInSession:(NIMSession *)session;
@end

示例

//  NIMSessionViewController.m
- (void)onRecvMessages:(NSArray *)messages
{
    ....
    //会话页直接监听收到消息后的回调,并由于当前页是在会话,直接认为已读
    if ([session isEqual:self.session])
    {
        //只有当消息所属会话时会话页表示的会话时,才标记已读
        [[NIMSDK sharedSDK].conversationManager markAllMessagesReadInSession:self.session];
    }
    ....
}

单条消息的删除


@protocol NIMConversationManager <NSObject>

/**
 *  删除某条消息
 *
 *  @param message 待删除的聊天消息
 */
- (void)deleteMessage:(NIMMessage *)message;

@end

调用此方法时,如果删除的是最后一条消息,消息所属的最近会话的 lastMessage 属性会自动变成上一条消息(没有则为空消息),同时触发最近消息修改的回调。

单个会话批量消息删除

@protocol NIMConversationManager <NSObject>
/**
 *  删除某个会话的所有消息
 *
 *  @param session 待删除会话
 *  @param option 删除消息选项
 */
- (void)deleteAllmessagesInSession:(NIMSession *)session
                            option:(nullable NIMDeleteMessagesOption *)option;
@end

NIMDeleteMessagesOption 参数列表

参数 类型 说明
removeSession BOOL 是否移除对应最近会话,批量删除消息时是否移除最近会话,默认为 NO,设置为 YES 时将同时删除最近会话信息
removeTable BOOL 是否删除消息表,默认情况下云信采用标记的方式进行消息删除,如果设置为 YES,将一并移除对应的消息表,进而减少消息表数量,加快 I/O
@protocol NIMConversationManager <NSObject>
/**
 *  删除某个最近会话
 *
 *  @param recentSession 待删除的最近会话
 *  @discussion 异步方法,删除最近会话,但保留会话内消息
 */
- (void)deleteRecentSession:(NIMRecentSession *)recentSession
@end

只会删除最近会话,但保留会话内消息。调用时,总未读消息数会减去当前会话的未读数。调用此方法触发最近消息删除的回调。

@protocol NIMConversationManager <NSObject>
/**
 *  删除所有会话消息
 *
 *  @param option 删除消息选项
 *  @discussion 调用这个接口只会触发allMessagesDeleted这个回调,其他针对单个recentSession的回调都不会被调用
 */
- (void)deleteAllMessages:(NIMDeleteMessagesOption *)option
@end

NIMDeleteMessagesOption 参数列表

属性列表

参数 类型 说明
removeSession BOOL 是否移除对应最近会话,批量删除消息时是否移除最近会话,默认为 NO,设置为 YES 时将同时删除最近会话信息
removeTable BOOL 是否删除消息表,默认情况下云信采用标记的方式进行消息删除,如果设置为 YES,将一并移除对应的消息表,进而减少消息表数量,加快 I/O

部分类型消息支持不发送直接写入本地,目前支持的类型为: 1.文本类型 ( NIMMessageTypeText ) 2.提醒类型 ( NIMMessageTypeTip ) 3.自定义类型 ( NIMMessageTypeCustom )

原型

@protocol NIMConversationManager <NSObject>
/**
 *  写入消息
 *
 *  @param message 需要更新的消息
 *  @param session 需要更新的会话
 *  @param completion 完成后的回调
 *  @discussion 当保存消息成功之后,会收到 NIMChatManagerDelegate 中的 onRecvMessages: 回调。目前支持消息类型:NIMMessageTypeText,NIMMessageTypeTip,NIMMessageTypeCustom
 */
- (void)saveMessage:(NIMMessage *)message
         forSession:(NIMSession *)session
         completion:(nullable NIMUpdateMessageBlock)completion;
@end

属性列表

参数 类型 说明
message NIMMessage 需要写入的没有被发送的消息,支持类型见上文
session NIMSession 消息所在的会话
completion NIMUpdateMessageBlock 完成后的回调

方法为异步写入,无须开发者在上层单独开线程,直接在当前线程调用即可。

消息的部分属性支持在本地更新,目前可更新的字段为本地扩展字段 LocalExt 以及自定义消息的附件对象 messageObject

原型

@protocol NIMConversationManager <NSObject>
/**
 *  更新本地已存的消息记录
 *
 *  @param message 需要更新的消息
 *  @param session 需要更新的会话
 *  @param completion 完成后的回调
 *  @discussion 为了保证存储消息的完整性,提供给上层调用的消息更新接口只允许更新如下字段:所有消息的本地拓展字段(LocalExt)和自定义消息的消息对象(messageObject)
 */
- (void)updateMessage:(NIMMessage *)message
           forSession:(NIMSession *)session
           completion:(nullable NIMUpdateMessageBlock)completion;
@end

属性列表

参数 类型 说明
message NIMMessage 需要被更新的消息,支持的更新属性见上文
session NIMSession 消息所在的会话
completion NIMUpdateMessageBlock 完成后的回调

方法为异步写入,无须开发者在上层单独开线程,直接在当前线程调用即可。

最近会话提供本地扩展能力,可以用来开发 @ 以及 置顶 等功能。

开发者可以通过 RecentSessionlocalExt 接口读取扩展。

并通过调用 NIMConversationManager 修改本地扩展信息

原型

@protocol NIMConversationManager <NSObject>
/**
 *  更新最近会话的本地扩展
 *
 *  @param ext           扩展信息
 *  @param recentSession 要更新的最近会话
 *  @discussion          此扩展不会漫游到其他端,上层需要保证 NSDictionary 可以转换为 JSON。
 */
- (void)updateRecentLocalExt:(nullable NSDictionary *)ext
               recentSession:(NIMRecentSession *)recentSession;

@end

属性列表

参数 类型 说明
ext NSDictionary 扩展信息,上层需要保证能将 NSDictionary 转换为 JSON
recentSession NIMRecentSession 要更新的最近会话

示例

// NTESSessionUtil.m
+ (void)addRecentSessionAtMark:(NIMSession *)session
{
    //为会话添加 有人@你 的的标记
    NIMRecentSession *recent = [[NIMSDK sharedSDK].conversationManager recentSessionBySession:session];
    if (recent)
    {
        NSDictionary *localExt = recent.localExt?:@{};
        NSMutableDictionary *dict = [localExt mutableCopy];
        [dict setObject:@(YES) forKey:NTESRecentSessionAtMark];
        [[NIMSDK sharedSDK].conversationManager updateRecentLocalExt:dict recentSession:recent];
    }
}

历史记录


本地记录

原型

@protocol NIMConversationManager <NSObject>
/**
 *  从本地db读取一个会话里某条消息之前的若干条的消息
 *
 *  @param session 消息所属的会话
 *  @param message 当前最早的消息,没有则传入nil
 *  @param limit   个数限制
 *
 *  @return 消息列表,按时间从小到大排列
 */
- (nullable NSArray<NIMMessage *> *)messagesInSession:(NIMSession *)session
                                              message:(nullable NIMMessage *)message
                                                limit:(NSInteger)limit;
@end

属性列表

参数 类型 说明
session NIMSession 消息所属的会话
message NIMMessage 锚点消息
limit NSInteger 读取条数限制

传入一个已知的消息,返回比这个消息更早的消息集合。如果没有已知的消息,则传入 nil,返回最新的消息集合。

示例

// NIMSessionMsgDatasource.m

- (void)resetMessages:(void(^)(NSError *error)) handler
{    
    ...
    //获取到本地会话最后 limit 个消息并接到数据末尾
    NSArray<NIMMessage *> *messages = [[[NIMSDK sharedSDK] conversationManager] messagesInSession:_currentSession
                                                                                message:nil
                                                                                    limit:_messageLimit];
    [self appendMessageModels:[self modelsWithMessages:messages]];
    ...
}
@protocol NIMConversationManager <NSObject>
/**
 *  根据消息Id获取消息
 *
 *  @param session    消息所属会话结合
 *
 *  @param messageIds 消息Id集合
 *
 *  @return 消息列表,按时间从小到大排列
 */
- (nullable NSArray<NIMMessage *> *)messagesInSession:(NIMSession *)session
                                           messageIds:(NSArray<NSString *> *)messageIds;
@end

属性列表

参数 类型 说明
session NIMSession 消息所属的会话
messageIds NSArray 消息Id集合
@protocol NIMConversationManager <NSObject>
/**
 *  搜索本地会话内消息
 *
 *  @param session 消息所属的会话
 *  @param option  搜索选项
 *  @param result  读取的消息列表结果
 *
 */
- (void)searchMessages:(NIMSession *)session
                option:(NIMMessageSearchOption *)option
                result:(nullable NIMSearchMessageBlock)result;
@end

以及搜索本地全局历史消息

@protocol NIMConversationManager <NSObject>
/**
 *  全局搜索本地消息
 *
 *  @param option 搜索选项
 *  @param result 读取的消息内容
 */
- (void)searchAllMessages:(NIMMessageSearchOption *)option
                result:(NIMGlobalSearchMessageBlock)result
@end

其中 option 为搜索选项,具体选项如下:

参数 类型 说明
startTime NSTimeInterval 起始时间,默认为0
endTime NSTimeInterval 结束时间,默认为0,0 表示最大时间戳
limit NSUInteger 检索条数,默认100条,设置为0表示无条数限制
order NIMMessageSearchOrder 检索顺序,正向或反向查询消息历史
messageType NIMMessageType 查询的消息类型
allMessageTypes BOOL 搜索全部消息类型。默认为 NO,当设置为 YES 时,忽略 messageType 和 searchContent,同时返回所有的消息类型消息。
searchContent NSString 检索文本,如果需要搜索的消息类型为文本,会进行内容的匹配
fromIds NSArray 消息发起者列表

搜索将返回:时间在 (startTime,endTime) 之间,消息类型为指定类型,且匹配搜索内容或消息发起者列表的一定数量的消息。

云端记录

NIMConversationManager 支持从云信服务器上远程获取之前的聊天历史记录。

@protocol NIMConversationManager <NSObject>
/**
 *  从服务器上获取一个会话里某条消息之前的若干条的消息
 *
 *  @param session 消息所属的会话
 *  @param option  搜索选项
 *  @param result  读取的消息列表结果
 *  @discussion    此接口不支持查询聊天室消息,聊天室请参考 NIMChatroomManagerProtocol 中的查询消息接口。
 *
 */
- (void)fetchMessageHistory:(NIMSession *)session
                     option:(NIMHistoryMessageSearchOption *)option
                     result:(nullable NIMFetchMessageHistoryBlock)result;
@end

其中 option 为搜索选项,具体选项如下:

参数 类型 说明
startTime NSTimeInterval 需要检索的起始时间,没有则传入0。
endTime NSTimeInterval 当前最早的时间,没有则传入 0 。 此参数对聊天室会话无效。
limit NSUInteger 检索条数,上限为 100 条
order NIMMessageSearchOrder 检索顺序,正向或反向查询消息历史,此参数对聊天室会话无效
currentMessage NIMMessage 检索消息的当前参考消息,返回的消息结果集里不会包含这条消息,此参数对聊天室会话无效。
sync BOOL 是否在远程获取消息成功之后同步到本地数据库,同步只会保证消息数据写入本地但不触发回调。默认不同步,此参数对聊天室会话无效。

用户资料托管


NIMUserManager 提供了用户帐号资料管理。以下几个接口仅当选择云信托管用户资料时有效,如果开发者不希望云信获取自己的用户数据,则需自行维护用户资料。

NIMUserManager 里,使用 NIMUser 对用户进行封装。其中用户信息为 NIMUserInfo 属性。 具体的信息字段由 NIMUserInfoUpdateTag定义。 NIMUserInfoUpdateTag内置了多个常用信息字段(有格式校验)和一个拓展字段 NIMUserInfoUpdateTagEx 供开发者自行拓展。

NIMUser 原型

@interface NIMUser : NSObject

/**
 *  用户 Id
 */
@property (nullable,nonatomic,copy)   NSString    *userId;

/**
 *  备注名,长度限制为128个字符。
 */
@property (nullable,nonatomic,copy)   NSString    *alias;

/**
 *  扩展字段
 */
@property (nullable,nonatomic,copy)   NSString  *ext;

/**
 *  用户资料,仅当用户选择托管信息到云信时有效
 *  用户资料除自己之外,不保证其他用户资料实时更新
 *  其他用户资料更新的时机为: 1.调用 - (void)fetchUserInfos:completion: 方法刷新用户
 *                        2.收到此用户发来消息
 *                        3.程序再次启动,此时会同步好友信息
 */
@property (nullable,nonatomic,strong,readonly) NIMUserInfo *userInfo;

@end

属性列表

参数 类型 说明
userId NSString 用户 Id
alias NSString 备注名,长度限制为128个字符。
ext NSString 扩展字段
userInfo NIMUserInfo 用户资料,仅当用户选择托管信息到云信时有效,用户资料除自己之外,不保证其他用户资料实时更新

NIMUserInfo 原型


@interface NIMUserInfo : NSObject

/**
 *  用户昵称
 */
@property (nullable,nonatomic,copy,readonly) NSString *nickName;

/**
 *  用户头像
 */
@property (nullable,nonatomic,copy,readonly) NSString *avatarUrl;

/**
 *  用户头像缩略图
 *  @discussion 仅适用于使用云信上传服务进行上传的资源,否则无效。
 */
@property (nullable,nonatomic,copy,readonly) NSString *thumbAvatarUrl;

/**
 *  用户签名
 */
@property (nullable,nonatomic,copy,readonly) NSString *sign;

/**
 *  用户性别
 */
@property (nonatomic,assign,readonly) NIMUserGender gender;

/**
 *  邮箱
 */
@property (nullable,nonatomic,copy,readonly) NSString *email;

/**
 *  生日
 */
@property (nullable,nonatomic,copy,readonly) NSString *birth;

/**
 *  电话号码
 */
@property (nullable,nonatomic,copy,readonly) NSString *mobile;

/**
 *  用户自定义扩展字段
 */
@property (nullable,nonatomic,copy,readonly) NSString *ext;

@end

属性列表

参数 类型 说明
nickName NSString 用户昵称
avatarUrl NSString 用户头像
thumbAvatarUrl NSString 用户头像缩略图,仅适用于使用云信上传服务进行上传的资源,否则无效。
sign NSString 用户签名
gender NSString 用户性别
email NSString 邮箱
birth NSString 生日
mobile NSString 电话号码
ext NSString 用户自定义扩展字段

获取本地用户资料

@protocol NIMUserManager <NSObject>

/**
 *  从本地获取用户资料
 *
 *  @param  userId 用户id
 *
 *  @return NIMUser
 *
 *  @discussion 需要将用户信息交给云信托管,且数据已经正常缓存到本地,此接口才有效。
 *              用户资料除自己之外,不保证其他用户资料实时更新
 *              其他用户资料更新的时机为: 1.调用 - (void)fetchUserInfos:completion: 方法刷新用户
 *                                    2.收到此用户发来消息
 *                                    3.程序再次启动,此时会同步部分好友信息
 */
- (nullable NIMUser *)userInfo:(NSString *)userId;

@end

示例

    NIMUser *user = [[NIMSDK sharedSDK].userManager userInfo:@"userId"];

用户资料除自己之外,不保证其他用户资料实时更新。其他用户数据更新时机为:

获取服务器用户资料

@protocol NIMUserManager <NSObject>
/**
 *  从云信服务器批量获取用户资料
 *
 *  @param users       用户id列表
 *  @param completion  用户信息回调
 *
 *  @discussion 需要将用户信息交给云信托管,此接口才有效。调用此接口,不会触发 - (void)onUserInfoChanged: 回调。
 *              该接口会将获取到的用户信息缓存在本地,所以需要避免此接口的滥调,导致存储过多无用数据到本地而撑爆缓存:如在聊天室请求请求每个聊天室用户数据将造成缓存过大而影响程序性能
 *              本接口一次最多支持 150 个用户信息获取
 */
- (void)fetchUserInfos:(NSArray<NSString *> *)users
            completion:(nullable NIMUserInfoBlock)completion;
@end

此接口可以批量从服务器获取用户资料,出于用户体验和流量成本考虑,不建议应用频繁调用此接口。对于用户数据实时性要求不高的页面,应尽量调用读取本地缓存接口。

编辑用户资料

对于自己的用户资料信息,用户可以调用修改接口去针对某些字段进行修改。

原型:

@protocol NIMUserManager <NSObject>
/**
 *  修改自己的用户资料
 *
 *  @param values      需要更新的用户信息键值对
 *  @param completion  修改结果回调
 *
 *  @discussion   这个接口可以一次性修改多个属性,如昵称,头像等,传入的数据键值对是 {@(NIMUserInfoUpdateTag) : NSString},
 *                无效数据将被过滤。一些字段有修改限制,具体请参看 NIMUserInfoUpdateTag 的相关说明
 */
- (void)updateMyUserInfo:(NSDictionary<NSNumber *,NSString *> *)values
              completion:(nullable NIMUserBlock)completion;
@end

只允许用户编辑自己的资料。此接口可以一次性编辑多个属性。如昵称,头像等,传入的数据键值对是 {@(NIMUserInfoUpdateTag) : NSString},无效数据将被过滤。一些字段有修改格式校验。具体限制为:

属性名 具体字段 类型限制 格式校验
用户昵称 NIMUserInfoUpdateTagNick NSString
用户头像 NIMUserInfoUpdateTagAvatar NSString
用户签名 NIMUserInfoUpdateTagSign NSString
用户性别 NIMUserInfoUpdateTagGender NIMUserGender 只支持指定枚举
用户邮箱 NIMUserInfoUpdateTagEmail NSString 只支持合法邮箱
用户生日 NIMUserInfoUpdateTagBirth NSString yyyy-MM-dd
用户手机 NIMUserInfoUpdateTagBirth NSString 合法手机号 如13588888888、+(86)-13055555555
拓展字段 NIMUserInfoUpdateTagExt NSString

当修改用户资料成功后,会触发回调:

- (void)onUserInfoChanged:(NIMUser *)user;

用户关系托管


NIMUserManager 提供了用户用户关系管理,以及对用户会话的消息设置。在云信中,不是好友也允许聊天。用户关系如果不托管给云信,开发者需要自己在应用服务器维护。

好友关系

@protocol NIMUserManager <NSObject>
/**
 *  返回我的好友列表
 *
 *  @return NIMUser列表
 */
- (nullable NSArray<NIMUser *> *)myFriends;
@end

好友列表有本地缓存,缓存会在手动/自动登录后与服务器自动进行同步更新。接口返回的是 NIMUser 列表。 NIMUser 封装了开发者向云信托管的好友ID,对此好友的会话设置(是否需要消息提醒,是否是拉黑用户等), 以及用户的详细信息 NIMUserInfo (需要将用户信息交给云信托管)。

原型

@protocol NIMUserManager <NSObject>
/**
 *  添加好友
 *
 *  @param request    添加好友请求
 *  @param completion 完成回调
 */
- (void)requestFriend:(NIMUserRequest *)request
            completion:(NIMUserBlock)block;
@end

请求 NIMUserRequest 参数列表

参数 类型 说明
userId NSString 目标用户 ID
operation NIMUserOperation 操作类型
message NSString 附言

示例:

NIMUserRequest *request = [[NIMUserRequest alloc] init];
request.userId          = self.user.usrId;                            //封装用户ID
request.operation       = NIMUserOperationRequest;                    //封装验证方式
request.message         = @"跪求通过";                                 //封装自定义验证消息

当好友邀请发出后,对方会收到一条系统通知消息 ( NIMSystemNotification ) ,可以通过注册 NIMSystemNotificationManager 中的 addDelegate: 回调来监听。

系统通知的原型和参数说明,请参考系统通知章节

示例

//NIMSystemNotificationManager.m
//全局监听
- (void)viewDidLoad {
    ...
    [[NIMSDK sharedSDK].systemNotificationManager addDelegate:self];
}

好友通知类型 NIMSystemNotificationType 字段值统一为 NIMSystemNotificationTypeFriendAdd

好友的具体通知类型可在 NIMSystemNotification 中的 attachment 字段获取。好友通知类型的 attachment 统一为 NIMUserAddAttachment 类型,在获取时需要强类型转换

加好友的过程会分为多个状态(申请,拒绝,通过),在每个状态都会有系统通知回调。

参数 说明
NIMUserOperationAdd 添加好友,直接添加为好友,无需验证
NIMUserOperationRequest 请求添加好友
NIMUserOperationVerify 通过添加好友请求
NIMUserOperationReject 拒绝添加好友请求

示例

收到请求或者状态变更

//NTESSystemNotificationCell.m
 NIMSystemNotificationType type = self.notification.type;
 switch (type) {
    ...
    case NIMSystemNotificationTypeFriendAdd:
    {
        NSString *text = @"未知请求";
        id object = self.notification.attachment;
        if ([object isKindOfClass:[NIMUserAddAttachment class]]) {
            //强类型转换
            NIMUserOperation operation = [(NIMUserAddAttachment *)object operationType];
            //根据不同的操作类型去处理不同业务
            switch (operation) {
                case NIMUserOperationAdd:
                    // 对方直接加你为好友
                    break;
                case NIMUserOperationRequest:
                    // 对方请求加你为好友
                    break;
                case NIMUserOperationVerify:
                    //对方通过了你的好友请求
                    break;
                case NIMUserOperationReject:
                    //对方拒绝了你的好友请求
                    break;
                default:
                    break;
            }
        }
        self.detailTextLabel.text = text;
    }
    ...
 }

同意或拒绝请求

//SystemNotificationViewController.m
...
 NIMUserRequest *request = [[NIMUserRequest alloc] init];
            request.userId = notification.sourceID;
            request.operation = NIMUserOperationVerify;         
            [[[NIMSDK sharedSDK] userManager] requestFriend:request
                                                 completion];
...

为了让界面交互对部分系统通知做出一些修改,保存处理结果, 比如在好友邀请中,可能存在等待同意,成功,被拒绝等修改。系统通知专门提供了 handleStatus 做为上层自定义装填标记位。修改这个属性,后台会自动更新 db 中对应的数据,默认为 0。

示例

// SystemNotificationViewController.m
- (void)onAccept:(NIMSystemNotification *)notification
{
    ...
    case NIMSystemNotificationTypeFriendAdd:
    {
        NIMUserRequest *request = [[NIMUserRequest alloc] init];
        request.userId = notification.sourceID;
        request.operation = NIMUserOperationVerify;

        [[[NIMSDK sharedSDK] userManager] requestFriend:request
                                                completion:^(NSError *error) {
                                                    if (!error) {
                                                        //验证成功,将状态改掉
                                                        notification.handleStatus = NotificationHandleTypeOk;
                                                    }
                                                    else
                                                    {
                                                        //失败不做修改
                                                    }
                                                    //刷新界面
                                                    [wself.tableView reloadData];
                                                }];
    }
    ...
}
@protocol NIMUserManagerDelegate <NSObject>

@optional
/**
 *  好友状态发生变化 (在线)
 *
 *  @param user 用户对象
 */
- (void)onFriendChanged:(NIMUser *)user;
@end
@protocol NIMUserManager <NSObject>
/**
 *  删除好友
 *
 *  @param userId      好友Id
 *  @param completion  完成回调
 */
- (void)deleteFriend:(NSString *)userId
          completion:(nullable NIMUserBlock)completion;
@end

参数列表

参数 类型 说明
userId NSString 目标用户 ID
NIMUserBlock NIMUserBlock 完成回调
@protocol NIMUserManagerDelegate <NSObject>

@optional

/**
 *  好友状态发生变化 (在线)
 *
 *  @param user 用户对象
 */
- (void)onFriendChanged:(NIMUser *)user;
@end

黑名单

云信中,黑名单和好友关系是互相独立的,即修改好友关系不会影响黑名单关系,同时,修改黑名单也不会对好友关系进行操作。

@protocol NIMUserManager <NSObject>
/**
 *  返回所有在黑名单中的用户列表
 *
 *  @return 黑名单成员NIMUser列表
 */
- (nullable NSArray<NIMUser *> *)myBlackList;
@end

黑名单列表有本地缓存,缓存会在手动/自动登录后与服务器自动进行同步更新。接口返回的是 NIMUser 列表。 NIMUser 封装了开发者向云信托管的好友ID,对此好友的会话设置(是否需要消息提醒,是否是拉黑用户等), 以及用户的详细信息 NIMUserInfo (需要将用户信息交给云信托管)。

@protocol NIMUserManager <NSObject>
/**
 *  添加用户到黑名单
 *
 *  @param userId          用户Id
 *  @param completion      完成回调
 */
- (void)addToBlackList:(NSString *)userId
            completion:(NIMUserBlock)completion;
@end

参数列表

参数 类型 说明
userId NSString 目标用户 ID
NIMUserBlock NIMUserBlock 完成回调

拉黑成功后,会同时修改本地缓存,并触发回调:

@protocol NIMUserManagerDelegate <NSObject>

@optional
/**
 *  黑名单列表发生变化 (在线)
 */
- (void)onBlackListChanged;
@end
@protocol NIMUserManager <NSObject>

/**
 *  将用户从黑名单移除
 *
 *  @param userId        用户Id
 *  @param completion    完成回调
 */
- (void)removeFromBlackBlackList:(NSString *)userId
                      completion:(NIMUserBlock)completion;
@end

参数列表

参数 类型 说明
userId NSString 目标用户 ID
NIMUserBlock NIMUserBlock 完成回调

移除成功后,会同时修改本地缓存,并触发回调:

@protocol NIMUserManagerDelegate <NSObject>

@optional
/**
 *  黑名单列表发生变化 (在线)
 */
- (void)onBlackListChanged;

@end
@protocol NIMUserManager <NSObject>
/**
 *  判断用户是否已被拉黑
 *
 *  @param userId 用户Id
 *
 *  @return 是否已被拉黑
 */
- (BOOL)isUserInBlackList:(NSString *)userId;
@end

参数列表

参数 类型 说明
userId NSString 目标用户 ID

此接口是根据本地缓存数据来判断是否拉黑的,在调用时请保证本地缓存是正确的(登录后有正常完成数据同步)。

消息提醒

云信中,可以单独设置是否开启某个用户的消息提醒,即对某个用户静音。静音关系和好友关系是互相独立的,修改好友关系不会影响静音关系,同时,修改静音关系也不会对好友关系进行操作。

@protocol NIMUserManager <NSObject>
/**
 *  静音列表
 *
 *  @return 返回被我设置为取消消息通知的NIMUser列表
 */
- (NSArray<NIMUser *> *)myMuteUserList;
@end

静音列表有本地缓存,缓存会在手动/自动登录后与服务器自动进行同步更新。接口返回的是 NIMUser 列表。 NIMUser 封装了开发者向云信托管的好友ID,对此好友的会话设置(是否需要消息提醒,是否是拉黑用户等), 以及用户的详细信息 NIMUserInfo (需要将用户信息交给云信托管)。

@protocol NIMUserManager <NSObject>
/**
 *  设置消息提醒
 *
 *  @param notify       是否提醒
 *  @param userId       用户Id
 *  @param completion   完成回调
 */
- (void)updateNotifyState:(BOOL)notify
                  forUser:(NSString *)userId
               completion:(nullable NIMUserBlock)completion
@end

参数列表

参数 类型 说明
notify BOOL 是否提醒
userId NSString 目标用户 ID
NIMUserBlock NIMUserBlock 完成回调

设置成功之后,同时更新本地缓存数据。

@protocol NIMUserManager <NSObject>
/**
 *  是否需要消息通知
 *
 *  @param userId 用户Id
 *
 *  @return 是否需要消息通知
 */
- (BOOL)notifyForNewMsg:(NSString *)userId;
@end

参数列表

参数 类型 说明
userId NSString 目标用户 ID

此接口是根据本地缓存数据来判断是否有消息提醒的,在调用时请保证本地缓存是正确的(登录后有正常完成数据同步)。

当修改用户资料成功后,会触发回调:

@protocol NIMUserManagerDelegate <NSObject>

@optional
/**
 *  用户个人信息发生变化 (在线)
 *
 *  @param user 用户对象
 *  @discussion 出于性能和上层 APP 处理难易度的考虑,本地调用批量接口获取用户信息时不触发当前回调。
 */
- (void)onUserInfoChanged:(NIMUser *)user;
@end

群组功能


群组功能概述

群组功能对应的管理类为 NIMTeamManagerNIMTeamManager 提供了普通群 (Normal) 以及高级群 (Advanced) 两种形式的群聊功能。高级群拥有更多的权限操作,两种群聊形式在共有操作上保持了接口一致。推荐 APP 开发时只选择一种群类型进行开发。普通群和高级群在原则上是不能互相转换的,他们的群类型在创建时就已经确定。在 SDK 2.4.0 版本后,高级群可以拥有普通群的全部功能,推荐使用高级群进行开发。

开发手册中所提及的普通群都等同于 Demo 中的讨论组。普通群没有权限操作,适用于快速创建多人会话的场景。每个普通群只有一个管理员。管理员可以对群进行增减员操作,普通成员只能对群进行增员操作。在添加新成员的时候,并不需要经过对方同意。

高级群在权限上有更多的限制,权限分为群主、管理员、以及群成员。

获取群组

NIM SDK 在程序启动时会对本地群信息进行同步,所以只需要调用本地缓存接口获取群就可以了。 SDK 提供了批量获取自己的群接口、以及根据单个群 id 查询的接口。同样 SDK 也提供了远程获取群信息的接口。

本地获取

本地获取所有群组

原型

@protocol NIMTeamManager <NSObject>
/**
 *  获取所有群组
 *
 *  @return 返回所有群组
 */
- (nullable NSArray<NIMTeam *> *)allMyTeams;
@end

本地根据群 Id 获取群组

@protocol NIMTeamManager <NSObject>
/**
 *  根据群组ID获取具体的群组信息
 *
 *  @param teamId 群组ID
 *
 *  @return 群组信息
 */
- (nullable NIMTeam *)teamById:(NSString *)teamId;
@end

参数列表

参数 类型 说明
teamId NSString 群组 ID

由于同步策略只会同步自己所在的群。对于和登录用户无关的群,需要调用远程接口进行获取

@protocol NIMTeamManagerDelegate <NSObject>
/**
 *  获取群信息
 *
 *  @param teamId      群组ID
 *  @param completion  完成后的回调
 */
- (void)fetchTeamInfo:(NSString *)teamId
           completion:(nullable NIMTeamFetchInfoHandler)completion;
@end

参数列表

参数 类型 说明
teamId NSString 群组 ID
completion NIMTeamFetchInfoHandler 请求完成回调

如果获取的群是属于自己的群的话,则会更新本地缓存的群数据。

创建群组

@protocol NIMTeamManager <NSObject>
/**
 *  创建群组
 *
 *  @param option     创建群选项
 *  @param users      用户ID列表
 *  @param completion 完成后的回调
 */
- (void)createTeam:(NIMCreateTeamOption *)option
              users:(NSArray<NSString *> *)users
         completion:(nullable NIMTeamCreateHandler)completion
@end

option 提供以参数信息

参数 类型 说明
name NSString 群名
type NIMTeamType 群类型
intro NSString 群简介
announcement NSString 群公告
clientCustomInfo NSString 客户端自定义信息
postscript NSString 邀请他人的附言,高级群有效,普通群无需附言
joinMode NIMTeamJoinMode 群验证模式。高级群有效,默认为 NIMTeamJoinModeNoAuth
inviteMode NIMTeamInviteMode 群邀请权限,只有高级群有效,默认为 NIMTeamInviteModeManager
beInviteMode NIMTeamBeInviteMode 被邀请模式,只有高级群有效,默认为 NIMTeamBeInviteModeNeedAuth
updateInfoMode NIMTeamUpdateInfoMode 修改群信息权限,只有高级群有效,默认为 NIMTeamUpdateInfoModeManager
updateClientCustomMode NIMTeamUpdateClientCustomMode 修改群客户端自定义字段权限。只有高级群有效,默认为 NIMTeamUpdateClientCustomModeManager

加入群组

用户可以通过被动接受邀请和主动加入两种方式进入群组。

邀请用户入群

@protocol NIMTeamManager <NSObject>
/**
 *  邀请用户入群
 *
 *  @param users       用户 ID 列表
 *  @param teamId      群组 ID
 *  @param postscript  邀请附言
 *  @param completion  完成后的回调
 */
- (void)addUsers:(NSArray<NSString *>  *)users
          toTeam:(NSString *)teamId
      postscript:(NSString *)postscript
      completion:(nullable NIMTeamMemberHandler)completion;

@end

参数列表

参数 类型 说明
users NSArray 用户 ID 列表
teamId NSString 群组 ID
postscript NSString 邀请附言
completion NIMTeamMemberHandler 完成后的回调

请求完成后,如果是普通群,被邀请者将直接入群;如果是高级群,云信服务器会下发一条系统消息到目标用户,目标用户可以选择同意或者拒绝入群。

目标用户通过注册 NIMSystemNotificationManager 的监听

//注册
- (void)addListener
{
...
[[NIMSDK sharedSDK].systemNotificationManager addDelegate:self];
...
}

//监听
- (void)onReceiveSystemNotification:(NIMSystemNotification *)notification
{
   //balabala
}

会收到一条系统通知 NIMSystemNotification, 其类型属性 typeNIMSystemNotificationTypeTeamInvite。在通知中,可以获取如下信息

参数列表

参数 类型 说明
sourceID NSString 邀请人 ID
targetID NSString 邀请进入的群组 ID
postscript NSString 邀请附言

同意群邀请(仅限高级群)

@protocol NIMTeamManager <NSObject>
/**
 *  接受入群邀请
 *
 *  @param teamId     群组 ID
 *  @param invitorId  邀请者 ID
 *  @param completion 完成后的回调
 */
- (void)acceptInviteWithTeam:(NSString*)teamId
                   invitorId:(NSString*)invitorId
                  completion:(NIMTeamHandler)completion
@end

参数列表

参数 类型 说明
teamId NSString 群组 ID
invitorId NSString 邀请者 ID
completion NIMTeamHandler 完成后的回调

同意群邀请后,会自动加入进群组,并在群组中产生一条群通知消息

群通知消息解析过程示例

    //通过回调收到 NIMMessage,变量名为 message    
    NIMNotificationObject *object = message.messageObject;
    if (message.messageType == NIMMessageTypeNotification && object.notificationType == NIMNotificationTypeTeam)
    {
        //群通知消息解析
        NIMTeamNotificationContent *content = (NIMTeamNotificationContent*)object.content;

        //对群通知的具体内容 NIMTeamNotificationContent 进行业务
        ...
    }

拒绝群邀请(仅限高级群)

/**
 *  拒绝入群邀请
 *
 *  @param teamId       群组ID
 *  @param invitorId    邀请者ID
 *  @param rejectReason 拒绝原因
 *  @param completion   完成后的回调
 */
- (void)rejectInviteWithTeam:(NSString*)teamId
                   invitorId:(NSString*)invitorId
                rejectReason:(NSString*)rejectReason
                  completion:(NIMTeamHandler)completion

参数列表

参数 类型 说明
teamId NSString 群组 ID
invitorId NSString 邀请者 ID
rejectReason NSString 拒绝原因
completion NIMTeamHandler 完成后的回调

拒绝群邀请后,邀请人会收到一条系统通知 NIMSystemNotification, type 值为 NIMSystemNotificationTypeTeamApplyReject

主动申请入群(仅限高级群)

@protocol NIMTeamManager <NSObject>
/**
 *  群申请
 *
 *  @param teamId     群组 ID
 *  @param message    申请消息
 *  @param completion 完成后的回调
 */
- (void)applyToTeam:(NSString *)teamId
            message:(NSString *)message
         completion:(NIMTeamApplyHandler)block
@end

参数列表

参数 类型 说明
teamId NSString 群组 ID
message NSString 申请消息
completion NIMTeamApplyHandler 完成后的回调

请求完成后,云信服务器会下发一条系统消息 NIMSystemNotification, type 值为 NIMSystemNotificationTypeTeamApply 给群管理员。

管理员可以选择通过或者拒绝申请。

通过申请(仅限高级群)

@protocol NIMTeamManager <NSObject>
/**
 *  通过群申请
 *
 *  @param teamId       群组ID
 *  @param userId       申请的用户 ID
 *  @param completion   完成后的回调
 */
- (void)passApplyToTeam:(NSString *)teamId
                 userId:(NSString *)userId
             completion:(NIMTeamApplyHandler)block
@end

参数列表

参数 类型 说明
teamId NSString 群组 ID
userId NSString 用户 ID
completion NIMTeamApplyHandler 完成后的回调

通过申请后,会自动加入进群组,并在群组中产生一条群通知消息 ( 和上述 同意群邀请 表现一致 )

拒绝申请(仅限高级群)

@protocol NIMTeamManager <NSObject>
/**
 *  拒绝群申请
 *
 *  @param teamId       群组ID
 *  @param userId       申请的用户ID
 *  @param rejectReason 拒绝理由
 *  @param completion   完成后的回调
 */
- (void)rejectApplyToTeam:(NSString *)teamId
                   userId:(NSString *)userId
             rejectReason:(NSString *)rejectReason
               completion:(NIMTeamHandler)block
@end

请求完成后,云信服务器会下发一条系统消息 NIMSystemNotification, type 值为 NIMSystemNotificationTypeTeamIviteReject 给申请者。

编辑群组资料

普通成员可以修改自己的群资料,管理员以上权限的群成员可以修改他人群资料以及群组信息。当修改完群组资料后,会收到一条类型为 群组资料变更 (NIMTeamNotificationContent) 的群组通知消息,具体可参考 群组通知

具体包括:

修改群成员昵称

@protocol NIMTeamManager <NSObject>
/**
 *  更新成员群昵称
 *
 *  @param userId       群成员ID
 *  @param newNick      新的群成员昵称
 *  @param teamId       群组ID
 *  @param completion   完成后的回调
 */
- (void)updateUserNick:(NSString *)userId
               newNick:(NSString *)newNick
                inTeam:(NSString *)teamId
            completion:(NIMTeamHandler)completion
@end

参数列表

参数 类型 说明
userId NSString 群组 ID
newNick NSString 用户 ID
teamId NSString 完成后的回调
completion NIMTeamHandler 完成后的回调

修改群名称

@protocol NIMTeamManager <NSObject>
/**
 *  更新群组名称
 *
 *  @param teamName   群组名称
 *  @param teamId     群组ID
 *  @param completion 完成后的回调
 */
- (void)updateTeamName:(NSString *)teamName
                teamId:(NSString *)teamId
            completion:(NIMTeamHandler)completion
@end

参数列表

参数 类型 说明
teamName NSString 群组名称
teamId NSString 群组 ID
completion NIMTeamHandler 完成后的回调

修改群头像

@protocol NIMTeamManager <NSObject>
/**
 *  更新群组头像
 *
 *  @param teamAvatarUrl 群组头像 Url
 *  @param teamId        群组ID
 *  @param completion    完成后的回调
 */
- (void)updateTeamAvatar:(NSString *)teamAvatarUrl
                  teamId:(NSString *)teamId
              completion:(NIMTeamHandler) completion
@end

参数列表

参数 类型 说明
teamAvatarUrl NSString 群组头像 Url
teamId NSString 群组 ID
completion NIMTeamHandler 完成后的回调

修改群介绍

@protocol NIMTeamManager <NSObject>
/**
 *  更新群介绍
 *
 *  @param intro       群介绍
 *  @param teamId      群组ID
 *  @param completion  完成后的回调
 */
- (void)updateTeamIntro:(NSString *)intro
                 teamId:(NSString *)teamId
             completion:(NIMTeamHandler)block
@end

参数列表

参数 类型 说明
intro NSString 群介绍
teamId NSString 群组 ID
completion NIMTeamHandler 完成后的回调

修改群公告

@protocol NIMTeamManager <NSObject>
/**
 *  更新群公告
 *
 *  @param announcement 群公告
 *  @param teamId       群组ID
 *  @param completion   完成后的回调
 */
- (void)updateTeamAnnouncement:(NSString *)announcement
                        teamId:(NSString *)teamId
                    completion:(NIMTeamHandler)completion
@end

参数列表

参数 类型 说明
announcement NSString 群公告
teamId NSString 群组 ID
completion NIMTeamHandler 完成后的回调

修改群验证方式

@protocol NIMTeamManager <NSObject>
/**
 *  更新群组验证方式
 *
 *  @param joinMode   验证方式
 *  @param teamId     群组ID
 *  @param completion 完成后的回调
 */
- (void)updateTeamJoinMode:(NIMTeamJoinMode)joinMode
                    teamId:(NSString *)teamId
                completion:(NIMTeamHandler)completion
@end

参数列表

参数 类型 说明
joinMode NIMTeamJoinMode 验证方式
teamId NSString 群组 ID
completion NIMTeamHandler 完成后的回调

修改被邀请人验证方式

@protocol NIMTeamManager <NSObject>
/**
 *  更新群组被邀请人验证方式
 *
 *  @param beInviteMode 邀请方式
 *  @param teamId       群组ID
 *  @param completion   完成后的回调
 */
- (void)updateTeamBeInviteMode:(NIMTeamBeInviteMode)beInviteMode
                        teamId:(NSString *)teamId
                    completion:(NIMTeamHandler)completion;
@enc

参数列表

参数 类型 说明
beInviteMode NIMTeamBeInviteMode 邀请方式
teamId NSString 群组 ID
completion NIMTeamHandler 完成后的回调

修改谁可以邀请其他人入群

@protocol NIMTeamManager <NSObject>
/**
 *  更新群组邀请他人方式
 *
 *  @param inviteMode  邀请方式
 *  @param teamId      群组ID
 *  @param completion  完成后的回调
 */
- (void)updateTeamInviteMode:(NIMTeamInviteMode)inviteMode
                      teamId:(NSString *)teamId
                  completion:(NIMTeamHandler)completion
@end

参数列表

参数 类型 说明
inviteMode NIMTeamInviteMode 邀请方式
teamId NSString 群组 ID
completion NIMTeamHandler 完成后的回调

修改谁可以修改群资料

@protocol NIMTeamManager <NSObject>
/**
 *  更改群组更新信息的权限
 *
 *  @param updateInfoMode 修改谁有权限更新群组信息
 *  @param teamId         群组ID
 *  @param completion     完成后的回调
 */
- (void)updateTeamUpdateInfoMode:(NIMTeamUpdateInfoMode)updateInfoMode
                          teamId:(NSString *)teamId
                      completion:(NIMTeamHandler)block
@end

参数列表

参数 类型 说明
updateInfoMode NIMTeamUpdateInfoMode 修改谁有权限更新群组信息
teamId NSString 群组 ID
completion NIMTeamHandler 完成后的回调

修改谁可以修改群自定义属性

@protocol NIMTeamManager <NSObject>
/**
 *  更改群组更新自定义字段的权限
 *
 *  @param clientCustomMode 修改谁有权限更新群组自定义字段
 *  @param teamId           群组ID
 *  @param completion       完成后的回调
 */
- (void)updateTeamUpdateClientCustomMode:(NIMTeamUpdateClientCustomMode)clientCustomMode
                                  teamId:(NSString *)teamId
                              completion:(NIMTeamHandler)block
@end

参数列表

参数 类型 说明
clientCustomMode NIMTeamUpdateClientCustomMode 修改谁有权限更新群组自定义字段
teamId NSString 群组 ID
completion NIMTeamHandler 完成后的回调

管理群组权限

高级群群主可以对群进行权限管理,权限管理包括:

提升管理员

@protocol NIMTeamManager <NSObject>
/**
 *  添加管理员
 *
 *  @param teamId      群组ID
 *  @param users       需要添加为管理员的用户ID列表
 *  @param completion  完成后的回调
 */
- (void)addManagersToTeam:(NSString *)teamId
                    users:(NSArray<NSString *>  *)users
               completion:(NIMTeamHandler)completion
@end

参数列表

参数 类型 说明
clientCustomMode NIMTeamUpdateClientCustomMode 修改谁有权限更新群组自定义字段
teamId NSString 群组 ID
completion NIMTeamHandler 完成后的回调

移除管理员

@protocol NIMTeamManager <NSObject>
/**
 *  移除管理员
 *
 *  @param teamId     群组 ID
 *  @param users      需要移除管理员的用户ID列表
 *  @param completion 完成后的回调
 */
- (void)removeManagersFromTeam:(NSString *)teamId
                         users:(NSArray<NSString *>  *)users
                    completion:(NIMTeamHandler)completion

@end

参数列表

参数 类型 说明
teamId NSString 群组 ID
users NSArray 需要移除管理员的用户 ID 列表
completion NIMTeamHandler 完成后的回调

转让群

@protocol NIMTeamManager <NSObject>
/**
 *  移交群主
 *
 *  @param teamId     群组 ID
 *  @param newOwnerId 新群主 ID
 *  @param isLeave    是否同时离开群组
 *  @param completion 完成后的回调
 */
- (void)transferManagerWithTeam:(NSString *)teamId
                     newOwnerId:(NSString *)newOwnerId
                        isLeave:(BOOL)isLeave
                     completion:(NIMTeamHandler)block
@end

参数列表

参数 类型 说明
teamId NSString 群组 ID
newOwnerId NSString 新群主 ID
isLeave BOOL 是否同时离开群组
completion NIMTeamHandler 完成后的回调

群组成员

群组成员信息不同于用户资料,主要是和群组关联的信息。同一个用户在不同群组中自己的群成员信息也不一样。群成员信息包括群昵称,进群时间,群成员类型等等。

原型

@interface NIMTeamMember : NSObject
/**
 *  群ID
 */
@property (nullable,nonatomic,copy,readonly)         NSString *teamId;

/**
 *  群成员ID
 */
@property (nullable,nonatomic,copy,readonly)         NSString *userId;

/**
 *  邀请者ID
 *  @dicusssion 此字段仅当该成员为自己时有效。不允许查看其他群成员的邀请者
 */
@property (nullable,nonatomic,copy,readonly)         NSString *invitor;

/**
 *  群成员类型
 */
@property (nonatomic,assign)                NIMTeamMemberType  type;


/**
 *  群昵称
 */
@property (nullable,nonatomic,copy)         NSString *nickname;


/**
 *  被禁言
 */
@property (nonatomic,assign,readonly)       BOOL isMuted;

/**
 *  进群时间
 */
@property (nonatomic,assign,readonly)       NSTimeInterval createTime;


/**
 *  新成员群自定义信息
 */
@property (nullable,nonatomic,copy)        NSString *customInfo;

@end

属性列表

参数 类型 说明
teamId NSString 群组ID
userId NSString 群成员 ID
invitor NSString 邀请者 ID,此字段仅当该成员为自己时有效。不允许查看其他群成员的邀请者
type NIMTeamMemberType 群成员类型
nickname NSString 群昵称
isMuted BOOL 是否被禁言
createTime NSTimeInterval 进群时间
customInfo NSString 新成员群自定义信息

对于群成员, SDK 不保证有本地数据,每次登录会同步所在群的群成员。对于同步或主动远程获取过的群成员,SDK会把数据缓存在本地。

当本地缓存群成员资料发生变动时,会通过 NIMTeamManagerDelegate 的回调通知上层,详见群组委托

获取群成员

@protocol NIMTeamManager <NSObject>
/**
 *  获取群组成员
 *
 *  @param teamId     群组ID
 *  @param completion 完成后的回调
 */
- (void)fetchTeamMembers:(NSString *)teamId
              completion:(NIMTeamMemberHandler)completion
@end

参数列表

参数 类型 说明
teamId NSString 群组 ID
completion NIMTeamMemberHandler 完成后的回调

绝大多数情况这个请求都是从本地读取缓存并同步返回,但是由于群成员信息量较大, SDK 采取的是登录后延迟拉取的策略。考虑到用户网络等问题, SDK 有可能没有及时缓存群成员信息,那么这个请求将是个带网络请求的异步操作(增量请求)。同时这个接口会去请求本地没有缓存的群用户的资料信息,但不会触发 - (void)onUserInfoChanged: 回调。

获取到的群成员只有云信服务器托管的群相关数据,需要开发者结合自己管理的用户数据进行界面显示。

修改自己的群成员自定义属性

@protocol NIMTeamManager <NSObject>
/**
 *  更新成员群自定义属性
 *
 *  @param newInfo      新的自定义属性
 *  @param teamId       群组ID
 *  @param completion   完成后的回调
 */
- (void)updateMyCustomInfo:(NSString *)newInfo
                    inTeam:(NSString *)teamId
                completion:(NIMTeamHandler)completion
@end

参数列表

参数 类型 说明
newInfo NSString 新的自定义属性
teamId NSString 群组 ID
completion NIMTeamHandler 完成后的回调

修改后,其他在线用户自动同步获得修改后的属性。

用户退群

@protocol NIMTeamManager <NSObject>
/**
 *  退出群组
 *
 *  @param teamId     群组ID
 *  @param completion 完成后的回调
 */
- (void)quitTeam:(NSString *)teamId
      completion:(NIMTeamHandler)completion
@end

参数列表

参数 类型 说明
teamId NSString 群组 ID
completion NIMTeamHandler 完成后的回调

用户退群成功后,相关会话信息仍然会保留,但不再能接收关于此群的消息。

禁言用户

@protocol NIMTeamManager <NSObject>
/**
 *  群成员禁言
 *
 *  @param mute        是否禁言
 *  @param userId      用户ID
 *  @param teamId      群组ID
 *  @param completion  经验操作完成后的回调
 */
- (void)updateMuteState:(BOOL)mute
                 userId:(NSString *)userId
                 inTeam:(NSString *)teamId
             completion:(NIMTeamHandler)block
@end

禁言用户后,云信服务器会下发一条提示该用户被禁言的群组通知消息。

参数列表

参数 类型 说明
mute BOOL 是否禁言
userId NSString 用户 ID
teamId BOOL 群组 ID
completion NIMTeamHandler 完成后的回调

踢出用户

@protocol NIMTeamManager <NSObject>
/**
 *  从群组内移除成员
 *
 *  @param users       需要移除的用户ID列表
 *  @param teamId      群组ID
 *  @param completion  完成后的回调
 */
- (void)kickUsers:(NSArray<NSString *> *)users
         fromTeam:(NSString *)teamId
       completion:(NIMTeamHandler)completion
@end

被踢出的用户相关会话信息仍然会保留,但不再能接收关于此群的消息。

参数列表

参数 类型 说明
users NSArray 需要移除的用户ID列表
teamId NSString 群组 ID
completion NIMTeamHandler 完成后的回调

解散群

@protocol NIMTeamManager <NSObject>
/**
 *  解散群组
 *
 *  @param teamId      群组ID
 *  @param completion  完成后的回调
 */
- (void)dismissTeam:(NSString*)teamId
         completion:(NIMTeamHandler)block
@end

参数列表

参数 类型 说明
teamId NSString 群组 ID
completion NIMTeamHandler 完成后的回调

群解散后,所有群用户关于此群会话会被保留,但是不能能够在此群会话里收发消息。

群组委托

用户的群信息会在以下条件下更新:

这些操作成功后,云信服务器会推送一条群通知,同时触发 SDK 更新群信息的委托事件:

@protocol NIMTeamManagerDelegate <NSObject>
/**
 *  群组更新回调
 *
 *  @param team 更新的群组
 */
- (void)onTeamUpdated:(NIMTeam *)team
@end

用户的群信息会在以下条件下移除:

这些操作成功后,云信服务器同样会推送一条群通知,同时触发 SDK 更新群信息的委托事件:

@protocol NIMTeamManagerDelegate <NSObject>
/**
 *  群组移除回调
 *
 *  @param team 被移除的群组
 */
- (void)onTeamRemoved:(NIMTeam *)team
@end

用户的群成员信息会在以下条件下更新

这些操作成功后,云信服务器同样会推送一条群通知,同时触发 SDK 更新群信息的委托事件:

@protocol NIMTeamManagerDelegate <NSObject>
/**
 *  群组成员变动回调,包括数量增减以及成员属性变动
 *
 *  @param team 变动的群组
 */
- (void)onTeamMemberChanged:(NIMTeam *)team;
@end

群组通知

群组通知是一种消息类型 ( NIMMessageTypeNotification ) ,用户在创建群或者进入群成功之后,任何关于群的变动,云信服务器都会下发一条群通知消息。群通知消息和其他消息一样,可从 NIMConversationManager 提供的消息查询接口中获取。

群组通知内容 NIMTeamNotificationContent 的字段说明:

群消息推送设置

SDK 提供了修改群消息通知的接口,上层可以通过设置这个选项以影响群消息的通知行为。当设置 notify 为 NO 时,群内消息将不会有 APNS 通知。当然上层也可以使用这一属性来决定收到在线消息时的 APP 表现 (是否响铃等)。

@protocol NIMTeamManager <NSObject>
/**
 *  修改群通知状态
 *
 *  @param notify       是否通知
 *  @param teamId       群组ID
 *  @param completion   完成后的回调
 */
- (void)updateNotifyState:(BOOL)notify
                   inTeam:(NSString *)teamId
               completion:(NIMTeamHandler)block;
@end

参数列表

参数 类型 说明
notify BOOL 是否通知
teamId BOOL 群组 ID
completion NIMTeamHandler 完成后的回调

群禁言

群组允许管理员将部分成员禁言,或者全体禁言。禁言属于高级功能,需要调用云信服务器接口,客户端 SDK 仅提供查询功能。

@protocol NIMTeamManager <NSObject>
/**
 *  获取群内被禁言的成员列表
 *
 *  @param teamId     群组ID
 *  @param completion 完成后的回调
 */
- (void)fetchTeamMutedMembers:(NSString *)teamId
                    completion:(nullable NIMTeamMemberHandler)completion;
@end

参数列表

参数 类型 说明
teamId BOOL 群组 ID
completion NIMTeamHandler 完成后的回调

绝大多数情况这个请求都是从本地读取缓存并同步返回,但是由于群成员信息量较大, SDK 采取的是登录后延迟拉取的策略。

考虑到用户网络等问题, SDK 有可能没有及时缓存群成员信息,那么这个请求将是个带网络请求的异步操作(增量请求)。

同时这个接口会去请求本地没有缓存的群用户的资料信息,但不会触发 - (void)onUserInfoChanged: 回调。

如果群处于全体禁言状态,则禁言用户列表无效。

@interface NIMTeam : NSObject
/**
 *  群组是否正在全员禁言
 *  @discussion 只有高级群有效
 */
- (BOOL)inAllMuteMode;
@end

自定义拓展

SDK 提供了群信息的拓展接口,开发者可以自行定义内容。

@protocol NIMTeamManager <NSObject>
/**
 *  更新群自定义信息
 *
 *  @param info         群自定义信息
 *  @param teamId       群组ID
 *  @param completion   完成后的回调
 */
- (void)updateTeamCustomInfo:(NSString *)info
                      teamId:(NSString *)teamId
                  completion:(NIMTeamHandler)block
@end

参数列表

参数 类型 说明
info NSString 群自定义信息
teamId NSString 群组 ID
completion NIMTeamHandler 完成后的回调

修改后会触发群信息变更的回调,详见群组委托

开发者可以通过 NIMTeam 的两个属性读取拓展信息:

@interface NIMTeam : NSObject
/**
 *  群服务端自定义信息
 */
@property (nonatomic,copy,readonly)  NSString *serverCustomInfo;
@end
@interface NIMTeam : NSObject
/**
 *  群客户端自定义信息
 */
@property (nonatomic,copy,readonly)  NSString *clientCustomInfo;
@end

聊天室


在集成聊天室之前,推荐开发者首先阅读这里

聊天室功能概述

聊天室功能对应的管理类为 NIMChatroomManagerNIMChatroomManager 提供了聊天室的业务管理,如进入/退出聊天室,获取相关信息以及权限操作等。目前不支持通过 SDK 接口建立/解散聊天室。

聊天室模型特点:

进入聊天室

用户要在聊天室内说话,必须先调用接口进入此聊天室。用户进入聊天室后,不会收到此聊天室的历史消息推送。如有历史消息需求,可以调用消息查询接口进行显示。

@protocol NIMChatroomManager <NSObject>
/**
 *  进入聊天室
 *
 *  @param request    进入聊天室请求
 *  @param completion 进入完成后的回调
 */
- (void)enterChatroom:(NIMChatroomEnterRequest *)request
           completion:(NIMChatroomEnterHandler)completion;
@end

NIMChatroomEnterRequest 参数列表

参数 类型 说明
roomId NSString 聊天室 ID
roomNickname NSString 聊天室昵称
roomAvatar NSString 聊天室头像,上层可以自主设置在聊天室内的头像,没有设置则使用用户本身的信息
roomExt NSString 本人的聊天室成员信息拓展字段,仅对当次进入有效
roomNotifyExt NSString 聊天室事件通知拓展字段
retryCount NSInteger 聊天室重连次数,默认为三次,设置成 0 后一旦一次连接失败后,SDK 将不在重试。 APP 可以根据自己的需求进行设置

NIMChatroomEnterRequest 中包含了聊天室的基本数据信息,包括需要进入的聊天室 id 和一些供用户自定义的扩展字段,后续当前用户的所有聊天室消息都会带上登录时设置的扩展字段。

扩展包括:

进入聊天室会建立新的连接,不同的聊天室对应着不同的连接,开发者可以监听连接状态做一些业务处理。

@protocol NIMChatroomManagerDelegate <NSObject>
/**
 *  聊天室连接状态变化
 *
 *  @param roomId 聊天室Id
 *  @param state  当前状态
 */
- (void)chatroom:(NSString *)roomId connectionStateChanged:(NIMChatroomConnectionState)state;
@end

NIMChatroomConnectionState 枚举列表

参数 说明
NIMChatroomConnectionStateEntering 0 正在进入聊天室
NIMChatroomConnectionStateEnterOK 1 进入聊天室成功
NIMChatroomConnectionStateEnterFailed 2 进入聊天室失败
NIMChatroomConnectionStateLoseConnection 3 和聊天室失去连接

当进入聊天室后,再发生掉线问题时,SDK 将自动重连,无需开发者再次调用进入房间接口。

在重连时,可能遇到一些特殊网络错误(如聊天室用户被封禁,聊天室状态异常),会触发以下回调,开发者应该在这个回调中退出聊天室界面。

@protocol NIMChatroomManagerDelegate <NSObject>
/**
 *  聊天室自动登录出错
 *
 *  @param roomId 聊天室Id
 *  @param error  自动登录出错原因
 */
- (void)chatroom:(NSString *)roomId autoLoginFailed:(NSError *)error;
@end

离开聊天室

离开聊天室时,会断开聊天室对应的连接,并不再收到关于此聊天室的任何消息。

@protocol NIMChatroomManager <NSObject>
/**
 *  离开聊天室
 *
 *  @param roomId     聊天室ID
 *  @param completion 离开聊天室的回调
 */
- (void)exitChatroom:(NSString *)roomId
          completion:(NIMChatroomHandler)completion;
@end

参数列表

参数 类型 说明
roomId NSString 聊天室 ID
completion NIMChatroomHandler 离开聊天室的回调

当用户被踢或者聊天室关闭时,会触发被踢回调,这个时候也会断开聊天室对应的连接:

@protocol NIMChatroomManagerDelegate <NSObject>
/**
 *  被踢回调
 *
 *  @param roomId   被踢的聊天室Id
 *  @param reason   被踢原因
 */
- (void)chatroom:(NSString *)roomId beKicked:(NIMChatroomKickReason)reason;
@end

NIMChatroomKickReason 枚举列表

参数 说明
NIMChatroomKickReasonInvalidRoom 1 聊天室已经解散
NIMChatroomKickReasonByManager 2 被聊天室管理员踢出
NIMChatroomKickReasonByConflictLogin 3 多端被踢
NIMChatroomKickReasonBlacklist 5 被拉黑

聊天室消息收发

聊天室消息收发接口与普通消息收发统一,在发送消息时指定会话类型为聊天室即可。会话 id 即为聊天室 id。

查询聊天室消息历史

进入聊天室时,不会下发关于聊天室的历史消息,可以通过下面的接口查询聊天室消息历史。

@protocol NIMChatroomManager <NSObject>
/**
 *  查询服务器保存的聊天室消息记录
 *
 *  @param roomId  聊天室ID
 *  @param option  查询选项
 *  @param result   完成回调
 */
- (void)fetchMessageHistory:(NSString *)roomId
                     option:(NIMHistoryMessageSearchOption *)option
                     result:(NIMFetchChatroomHistoryBlock)completion;
@end

NIMHistoryMessageSearchOption 参数列表 (部分字段对聊天室消息搜索选项无效,已过滤)

参数 类型 说明
startTime NSTimeInterval 检索消息起始时间,需要检索的起始时间,没有则传入0。
limit NSUInteger 检索条数,最大限制 100 条
order NIMMessageSearchOrder 检索顺序

获取聊天室信息

此接口可以远程获取聊天室信息,NIM SDK 不会缓存聊天室信息,开发者需要根据业务自己做好缓存。

@protocol NIMChatroomManager <NSObject>
/**
 *  获取聊天室信息
 *
 *  @param roomId     聊天室ID
 *  @param completion 获取聊天室信息的回调
 *  @discussion 只有已进入聊天室才能够获取对应的聊天室信息
 */
- (void)fetchChatroomInfo:(NSString *)roomId
               completion:(NIMChatroomInfoHandler)completion;
@end

参数列表

参数 类型 说明
roomId NSString 聊天室 ID
completion NIMChatroomInfoHandler 离开聊天室的回调

修改聊天室信息

此接口可以修改聊天室信息,调用完这个接口后,开发者应该自己修改内存缓存的 NIMChatroom 对象。

此接口需要生成 NIMChatroomUpdateRequest 对象来完成请求。

NIMChatroomUpdateRequest中的 needNotify 参数可以设置成功修改信息后云信服务器是否推送一条修改的聊天室消息通知。

NIMChatroomUpdateRequest中的 notifyExt 参数可以设置推送的聊天室消息通知里带的自定义扩展字段。

@protocol NIMChatroomManager <NSObject>
/**
 *  修改聊天室信息
 *
 *  @param request    聊天室修改请求
 *  @param completion 修改后完成的回调
 */
- (void)updateChatroomInfo:(NIMChatroomUpdateRequest *)request
                completion:(nullable NIMChatroomHandler)completion;
@end

NIMChatroomEnterRequest 参数列表

参数 类型 说明
roomId NSString 聊天室 ID
updateInfo NSDictionary 修改信息字段,修改传入的数据键值对是 {@(NIMChatroomUpdateTag) : NSString},无效数据将被过滤
needNotify BOOL 是否需要通知
notifyExt NSString 放到事件通知里的扩展字段

获取聊天室成员

此接口可以远程获取聊天室成员列表,NIM SDK 不会缓存聊天室成员列表,开发者需要根据业务自己做好缓存。 NIM SDK 提供两种方式获取聊天室成员:

@protocol NIMChatroomManager <NSObject>
/**
 *  获取聊天室成员
 *
 *  @param request    获取成员请求
 *  @param completion 请求完成回调
 */
- (void)fetchChatroomMembers:(NIMChatroomMemberRequest *)request
                  completion:(NIMChatroomMembersHandler)completion;
@end

NIMChatroomMemberRequest 参数列表

参数 类型 说明
roomId NSString 聊天室 ID
type NIMChatroomFetchMemberType 聊天室成员类型
lastMember NIMChatroomMember 最后一位成员锚点,不包括此成员。填nil会使用当前服务器最新时间开始查询,即第一页。
limit NSUInteger 获取聊天室成员个数
@protocol NIMChatroomManager <NSObject>
/**
 *  根据用户ID获取聊天室成员信息
 *
 *  @param request    获取成员请求
 *  @param completion 请求完成回调
 */
- (void)fetchChatroomMembersByIds:(NIMChatroomMembersByIdsRequest *)request
                    completion:(NIMChatroomMembersHandler)completion;
@end

NIMChatroomMembersByIdsRequest 参数列表

参数 类型 说明
roomId NSString 聊天室 ID
userIds NSArray 用户ID列表,最多20个

修改自己的聊天室成员信息

此接口可以修改聊天室成员信息,调用完这个接口后,开发者应该自己修改内存缓存的 NIMChatroomMember 对象。

此接口需要生成 NIMChatroomMemberInfoUpdateRequest 对象来完成请求。

NIMChatroomMemberInfoUpdateRequest中的 needNotify 参数可以设置成功修改信息后云信服务器是否推送一条修改的聊天室消息通知。

NIMChatroomMemberInfoUpdateRequest中的 notifyExt 参数可以设置推送的聊天室消息通知里带的自定义扩展字段。

- (void)updateMyChatroomMemberInfo:(NIMChatroomMemberInfoUpdateRequest *)request
                        completion:(nullable NIMChatroomHandler)completion;

聊天室权限管理

聊天室可以调整成员的类型,分固定成员和非固定成员两种,固定成员又分为创建者、管理员、普通成员和受限成员四种。禁言用户和拉黑用户都属于受限用户。

@protocol NIMChatroomManager <NSObject>
/**
 *  标记为聊天室管理员
 *
 *  @param request    更新请求
 *  @param completion 请求回调
 */
- (void)markMemberManager:(NIMChatroomMemberUpdateRequest *)request
              completion:(NIMChatroomHandler)completion;
@end
@protocol NIMChatroomManager <NSObject>
/**
 *  标记为聊天室普通成员
 *
 *  @param request    更新请求
 *  @param completion 请求回调
 */
- (void)markNormalMember:(NIMChatroomMemberUpdateRequest *)request
            completion:(NIMChatroomHandler)completion;
@end
@protocol NIMChatroomManager <NSObject>
/**
 *  更新用户聊天室黑名单状态
 *
 *  @param request    更新请求
 *  @param completion 请求回调
 */
- (void)updateMemberBlack:(NIMChatroomMemberUpdateRequest *)request
              completion:(NIMChatroomHandler)completion;
@end
@protocol NIMChatroomManager <NSObject>
/**
 *  更新用户聊天室静言状态
 *
 *  @param request    更新请求
 *  @param completion 请求回调
 */
- (void)updateMemberMute:(NIMChatroomMemberUpdateRequest *)request
            completion:(NIMChatroomHandler)completion;
@end

NIMChatroomMemberUpdateRequest 参数列表

参数 类型 说明
roomId NSString 聊天室 ID
userId NSString 用户 ID
enable BOOL 标记是否有效
notifyExt NSString 操作通知事件扩展

踢出成员

创建者或管理员可以将权限比自己低的用户踢出聊天室

@protocol NIMChatroomManager <NSObject>
/**
 *  将特定成员踢出聊天室
 *
 *  @param request    踢出请求
 *  @param completion 请求回调
 */
- (void)kickMember:(NIMChatroomMemberKickRequest *)request
        completion:(NIMChatroomHandler)completion;
@end

NIMChatroomMemberKickRequest 参数列表

参数 类型 说明
roomId NSString 聊天室 ID
userId NSString 用户 ID ,仅管理员可以踢人;如userId是管理员仅创建者可以踢
notifyExt NSString 被踢通知扩展字段

聊天室通知消息

在聊天室中所有的通知都以消息 NIMMessage 的形式展示,内部 messageObjectNIMNotificationTypeChatroom 类型的 NIMNotificationObject。上层开发在收到具体消息需要进行过滤和显示。目前支持的聊天室消息事件定义在 NIMChatroomEventType 枚举里,具体有:

解析聊天室通知消息的详细步骤:

  1. 判断消息是否为通知消息

    • 判断 NIMMessagemessageType 字段是否为 NIMMessageTypeNotification
  2. 判断通知消息是否为聊天室通知

    • NIMMessagemessageObject 字段强类型转换为 NIMNotificationObject
    • 判断转换后的 NIMNotificationObjectnotificationType 字段是否为 NIMNotificationTypeChatroom
  3. 解析聊天室通知的具体内容

    • NIMNotificationObjectcontent 字段强类型转换为 NIMChatroomNotificationContent
    • 查看转换后 NIMChatroomNotificationContent 的具体字段。

聊天室通知内容 NIMChatroomNotificationContent 的字段说明:

聊天室禁言

聊天室允许管理员将部分成员禁言,或者全体禁言。禁言属于高级功能,需要调用云信服务器接口,客户端 SDK 仅提供聊天室禁言的通知功能。

聊天室禁言通知类型被同样定义在了 NIMChatroomEventType 中,分别为

具体解析步骤请参考之前小节 聊天室通知消息

系统通知


概述

除消息通道外,NIM SDK 还提供系统通知这种通道用于消息之外的通知分发。目前有两种类型:内置系统通知和自定义系统通知。 现在主要包括群变动的相关通知,例如入群申请,入群邀请等,如果第三方应用还托管了好友关系,好友的添加、删除也是这个类型的通知。系统通知由 SDK 负责接收和存储,并提供较简单的未读数管理。

内置系统通知

内置系统通知由 NIMSystemNotification 表示。

原型

/**
 *  系统通知
 */
@interface NIMSystemNotification : NSObject
/**
 *  通知类型
 */
@property (nonatomic,assign,readonly)       NIMSystemNotificationType type;

/**
 *  时间戳
 */
@property (nonatomic,assign,readonly)       NSTimeInterval timestamp;

/**
 *  操作者
 */
@property (nullable,nonatomic,copy,readonly)         NSString *sourceID;

/**
 *  目标ID,群ID或者是用户ID
 */
@property (nullable,nonatomic,copy,readonly)         NSString *targetID;

/**
 *  附言
 */
@property (nullable,nonatomic,copy,readonly)         NSString *postscript;

/**
 *  是否已读
 *  @discussion 修改这个属性并不会修改db中的数据
 */
@property (nonatomic,assign)                BOOL read;

/**
 *  消息处理状态
 *  @discussion 修改这个属性,后台会自动更新db中对应的数据,SDK调用者可以使用这个值来持久化他们对消息的处理结果,默认为0
 */
@property (nonatomic,assign)                NSInteger handleStatus;


/**
 *  系统通知下发的自定义扩展信息
 */
@property (nullable,nonatomic,readonly)   NSString *notifyExt;

/**
 *  附件
 *  @discussion 额外信息,只有 好友添加
 *              好友添加的 attachment 为 NIMUserAddAttachment
 */
@property (nullable,nonatomic,strong,readonly)       id attachment;

@end

参数列表

参数 类型 说明
type NIMSystemNotificationType 通知类型
timestamp NSTimeInterval 时间戳
sourceID NSString 操作者
targetID NSString 目标ID,群ID或者是用户ID
postscript NSString 附言
read BOOL 是否已读,修改这个属性并不会修改db中的数据
handleStatus NSInteger 消息处理状态
notifyExt NSString 系统通知下发的自定义扩展信息
attachment id 附件,额外信息,目前只有 好友添加,attachment 为 NIMUserAddAttachment

所有的内置系统通知都是通过

@protocol NIMSystemNotificationManagerDelegate <NSObject>
@optional
/**
 *  收到系统通知回调
 *
 *  @param notification 系统通知
 */
-(void)onReceiveSystemNotification:(NIMSystemNotification *)notification;
@end

群相关系统通知请参考群组功能章节。

添加好友系统通知请参考好友系统通知章节。

下发给 APP。为了保证整个程序逻辑的一致性,APP 需要针对不同类型的系统通知进行相应的操作。

内置系统通知的本地存储:(以下接口分为全量和过滤,过滤接口需要传入过滤器 NIMSystemNotificationFilter,可以按类型选择获取内置系统通知)

NIMSystemNotificationFilter 原型

@interface NIMSystemNotificationFilter : NSObject
/**
 *  类型列表
 */
@property (nonatomic,copy)    NSArray<NSNumber *>     *notificationTypes;
@end

属性列表

属性 类型 说明
notificationTypes NSArray 类型列表

示例

NIMSystemNotificationFilter *filter = [[NIMSystemNotificationFilter alloc] init];
//只对 邀请人群 和 拒绝入群邀请 的系统通知做已读
filter.notificationTypes = @[@(NIMSystemNotificationTypeTeamIviteReject),@(NIMSystemNotificationTypeTeamInvite)];
[[[NIMSDK sharedSDK] systemNotificationManager] markAllNotificationsAsRead:filter];
@protocol NIMSystemNotificationManager <NSObject>
/**
 *  获取本地存储的系统通知
 *
 *  @param notification 当前最早系统消息,没有则传入nil
 *  @param limit        最大获取数
 *
 *  @return 系统消息列表
 */
- (NSArray *)fetchSystemNotifications:(NIMSystemNotification *)notification                                                        
                                  limit:(NSInteger)limit;
@end

参数列表

参数 类型 说明
notification NIMSystemNotification 当前最早系统消息,没有则传入nil
limit NSInteger 最大获取数
@protocol NIMSystemNotificationManager <NSObject>
/**
 *  获取本地存储的系统通知
 *
 *  @param notification 当前最早系统消息,没有则传入nil
 *  @param limit        最大获取数
 *  @param filter       过滤器
 *
 *  @return 系统消息列表
 */
- (NSArray *)fetchSystemNotifications:(NIMSystemNotification *)notification 
                                  limit:(NSInteger)limit                          
                                  filter:(NIMSystemNotificationFilter *)filter;    
@end

参数列表

参数 类型 说明
notification NIMSystemNotification 当前最早系统消息,没有则传入nil
limit NSInteger 最大获取数
filter NIMSystemNotificationFilter 过滤器
@protocol NIMSystemNotificationManager <NSObject>
/**
 *  未读系统消息数
 *
 *  @return 未读系统消息数
 */
- (NSInteger)allUnreadCount;
@end
@protocol NIMSystemNotificationManager <NSObject>
/**
 *  未读系统消息数
 *
 *  @param filter 过滤器
 *
 *  @return 未读系统消息数
 */
- (NSInteger)allUnreadCount:(nullable NIMSystemNotificationFilter *)filter;
@end

参数列表

参数 类型 说明
filter NIMSystemNotificationFilter 过滤器
@protocol NIMSystemNotificationManager <NSObject>
/**
 *  删除所有系统消息
 */
- (void)deleteAllNotifications;
@end
@protocol NIMSystemNotificationManager <NSObject>
/**
 *  删除所有系统消息
 */
- (void)deleteAllNotifications:(NIMSystemNotificationFilter *)filter;   
@end

参数列表

参数 类型 说明
filter NIMSystemNotificationFilter 过滤器
@protocol NIMSystemNotificationManager <NSObject>
/**
 *  删除单条系统消息
 *
 *  @param notification 系统消息
 */
- (void)deleteNotification:(NIMSystemNotification *)notification;
@end

参数列表

参数 类型 说明
notification NIMSystemNotification 当前最早系统消息,没有则传入nil
@protocol NIMSystemNotificationManager <NSObject>
/**
 *  标记所有系统消息为已读
 */
- (void)markAllNotificationsAsRead;
@end
@protocol NIMSystemNotificationManager <NSObject>
/**
 *  标记所有命中过滤器的系统消息为已读
 *
 *  @param filter 过滤器
 */
- (void)markAllNotificationsAsRead:(NIMSystemNotificationFilter *)filter;
@end

参数列表

参数 类型 说明
filter NIMSystemNotificationFilter 过滤器
@protocol NIMSystemNotificationManager <NSObject>
/**
 *  标记单条系统消息为已读
 *
 *  @param notification 系统消息
 */
- (void)markNotificationsAsRead:(NIMSystemNotification *)notification;
@end

参数列表

参数 类型 说明
notification NIMSystemNotification 当前最早系统消息,没有则传入nil

自定义

除内置系统通知外,NIM SDK 也额外提供自定义系统给开发者,方便开发者进行业务逻辑的通知。这个通知既可以由客户端发起也可以由开发者服务器发起。

注意:自定义通知和自定义消息的不同之处在于,自定义消息归属于 NIM SDK 消息体系内,适用于会话,由 SDK 存储在消息数据库中,与 NIM SDK 其他内建消息类型一同展现给用户。而自定义通知主要用于第三方的一些事件状态通知,SDK 不存储,也不解析这些通知。SDK 仅仅负责替第三方传递和通知这些事件,起到透传的作用,收到自定义通知后的持久化工作需要由上层开发负责。

发送自定义通知(客户端)

@protocol NIMSystemNotificationManager <NSObject>
/**
 *  发送自定义系统通知
 *
 *  @param notification 系统通知
 *  @param session      接收方
 *  @param completion   发送结果回调
 */
- (void)sendCustomNotification:(NIMCustomSystemNotification *)notification
                     toSession:(NIMSession *)session
                    completion:(NIMSystemNotificationHandler)completion
@end

参数列表

参数 类型 说明
notification NIMCustomSystemNotification 系统通知
session NIMSession 接收方
completion NIMSystemNotificationHandler 发送结果回调

客户端发起的自定义通知目前支持自定义如下字段:通知内容(推荐使用 json 组织),推送文案(如果没有则不进行 APNS 推送),是否只发给在线用户。最后一个字段的意义在于区分自定义通知的使用场景。选择只发给在线用户,当目标用户不在线时这条通知会被云信服务器丢弃,这种实现比较适合发送即时通知,如正在输入。反之云信服务器会缓存当前通知(有上限),并在目标用户上线后推送给目标用户。

仅支持个人和群。不支持聊天室。

接收自定义通知

@protocol NIMSystemNotificationManagerDelegate <NSObject>
/**
 *  收到自定义通知回调
 *  @discussion 这个通知是由开发者服务端/客户端发出,由我们的服务器进行透传的通知,SDK不负责这个信息的存储
 *  @param notification 自定义通知
 */
- (void)onReceiveCustomSystemNotification:(NIMCustomSystemNotification *)notification;
@end

参数列表

参数 类型 说明
notification NIMCustomSystemNotification 系统通知

APNs 推送


前期准备

[[NIMSDK sharedSDK] registerWithAppID:您的APPKEY
                              cerName:您的推送证书名];
- (void)registerAPNs
{
    if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerForRemoteNotifications)])
    {
        UIUserNotificationType types = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound |      UIRemoteNotificationTypeAlert;
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types
        categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    }
    else
    {
        UIRemoteNotificationType types = UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound |        UIRemoteNotificationTypeBadge;
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:types];
    }
}
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    [[NIMSDK sharedSDK] updateApnsToken:deviceToken];
}

推送时机

开发者在 发送消息自定义系统通知 时,可以指定是否同时进行推送服务。为了节省不必要的流量开销,只有当接收者的应用切换到后台时,云信推送服务才会开启;如果应用在前台,则不会有推送通知。如果有应用前台通信需求,建议开发者使用 自定义系统通知 ,并监听回调:

- (void)onReceiveCustomSystemNotification:(NIMCustomSystemNotification *)notification;

属性设置

NIM SDK 提供全局 APNS 属性设置,用于设置免打扰时间和推送样式,详细内容可以参考 NIMPushNotificationSetting

NIMPushNotificationSetting *setting =  [[[NIMSDK sharedSDK] apnsManager] currentSetting];
[[[NIMSDK sharedSDK] apnsManager] updateApnsSetting:setting
completion:^(NSError *error) {}];

APNS 多端设置 NIMPushNotificationMultiportConfig

- (NIMPushNotificationMultiportConfig *)currentConfig;
- (void)updateConfig:(NIMPushNotificationMultiportConfig *)config
          completion:(NIMApnsHandler)completion;

当桌面端在线时,可以通过设置 shouldPushNotificationWhenPCOnline 字段,控制是否需要发推送给手机端。

消息的推送设置

设置 NIMMessageapnsPayload 可以自定义推送参数。

用户在发送消息的时候,设置 NIMMessageapnsContent 属性进行消息推送内容设置。如果不设置 apnsContent 属性,将使用云信内置文案。

属性原型

@interface NIMMessage : NSObject
/**
 *  消息推送Payload
 *  @discussion 可以通过这个字段定义消息推送 Payload ,支持字段参考苹果技术文档,长度限制 2K
 */
@property (nullable,nonatomic,copy)   NSDictionary *apnsPayload;
@end

示例代码:

NIMAudioObject *audioObject = [[NIMAudioObject alloc] initWithSourcePath:filePath];
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = audioObject;
message.apnsContent = @"发来了一段语音";    //对方收到的推送文案

此时,对方的手机将会收到一条苹果推送,内容形式为 "昵称:"+"推送文案"。如果只需要推送文案的话,也可以将昵称部分隐藏

示例代码:

NIMMessage *message = [[NIMMessage alloc] init];
message.text = @"消息示例";
message.apnsContent = @"推送消息示例";    //对方收到的推送文案 
NIMMessageSetting *setting = [[NIMMessageSetting alloc] init];
setting.apnsWithPrefix = NO;
message.setting = setting;

如果本条消息不需要苹果推送,还可以将推送关闭

示例代码

NIMMessage *message = [[NIMMessage alloc] init];
message.text = @"不带推送的消息示例";
NIMMessageSetting *setting = [[NIMMessageSetting alloc] init];
setting.apnsEnabled = NO;
message.setting = setting;

默认情况下,消息的推送会让程序未读数加 1 。 具体表现为:如果程序在后台,则应用 icon 的 badge 上累加;当程序进入前台时,此消息被计入 SDK 的未读数,所在会话的 unreadCount 将会累加。

在发送时,可以设置将消息不计入未读数。示例代码

NIMMessage *message = [[NIMMessage alloc] init];
message.text = @"没有未读数的消息示例";
NIMMessageSetting *setting = [[NIMMessageSetting alloc] init];
setting.shouldBeCounted = NO;
message.setting = setting;

苹果推送所附带的未读数是通过设置推送 payload 里的 badge 参数。在云信 服务中,不支持直接设置 badge ,服务器会维护对每个用户维护一个当前未读数,当服务器收到一条未读消息后,会自动在未读数上累加后填入推送的 badge 字段推送给接收端。

开发者应该在程序每次推到后台时,统计本地所有未读,并设置 badge , 保证程序在前后台未读数一致

示例:

- (void)applicationDidEnterBackground:(UIApplication *)application {
    NSInteger count = [[[NIMSDK sharedSDK] conversationManager] allUnreadCount];
    [[UIApplication sharedApplication] setApplicationIconBadgeNumber:count];
}

如果应用本身除了云信未读之外还有其他未读的话,程序上的 icon 值应为 云信未读数 + 其他未读数 之和,但是由于云信服务器默认维护的未读数只有消息的未读数,这样会导致新来的消息推送未读数将不计入应用的其他未读。

这种情况下,需要客户端提交服务器应该管理的未读数。

原型

@protocol NIMApnsManager <NSObject>
/**
 *  注册获取 badge 数量的回调函数
 *
 *  @param handler 获取 badge 回调
 */
- (void)registerBadgeCountHandler:(NIMBadgeHandler)handler;
@end

在 NIMBadgeHandler 回调中,返回当前的未读数即可。SDK 会在合适的时机调用这个 block 。

消息推送的声音设置支持自定义,类似于推送的 payload , 开发者只需要将设置 key 为 sound 并以音频名为字符串 key , 填入消息的 apnsPayload 字段即可。需要注意推送音频的具体格式。具体请参考苹果官方文档

示例

NIMMessage *message = [[NIMMessage alloc] init];
message.text = @"消息示例";
message.apnsContent = @"发来了一条信息";
message.apnsPayload = @{@"sound":@"message.wav"};

推送可以在 payload 里附带其他信息,比如推送的消息 Id , 所在的会话等等,方便接收端收到推送后直接跳转。同样只需要在 apnsPayload 中设置即可。

示例

NIMMessage *message  = [[NIMMessage alloc] init];
message.text = @"消息示例";
message.apnsContent = @"发来了一条信息";
message.apnsPayload = @{@"sound":@"message.wav",@"messageId":message.messageId,@"balabala":@"pilipala"};

payload 结构

{
    aps =     {
        alert = "xxxxx";
        badge = 85;
        sound = default;
    };
    nim = 1;
}

其中 aps 为推送 payload 字段,包含了预定义的字段和自定义字段。 nim = 1 表示此条推送来自于云信推送,客户端可以根据这个键值对判断推送来源。

消息的成员推送选项

用户在发消息的时候,可以通过配置 NIMMessage 里的 apnsMemberOption 字段实现更为复杂的推送逻辑,目前这个字段只能在群会话中生效。

系统通知的推送设置

自定义系统通知也可以附带推送,字段结构流程与消息相同。

推送内容:

@interface NIMCustomSystemNotification : NSObject
/**
 *  apns推送文案
 *  @discussion 默认为nil,用户可以设置当前通知的推送文案
 */
@property (nullable,nonatomic,copy)                  NSString *apnsContent;
@end

推送 payload

@interface NIMCustomSystemNotification : NSObject
/**
 *  apns推送Payload
 *  @discussion 可以通过这个字段定义自定义通知的推送Payload,支持字段参考苹果技术文档,最多支持2K
 */
@property (nullable,nonatomic,copy)                  NSDictionary *apnsPayload;
@end

PushKit

PushKit 作为苹果公司在 iOS8 系统及以上引入的新类型推送,也被称作 voip push 。顾名思义,这种推送可以帮助我们提升 voip 应用的体验,优化 voip 应用的开发实现,降低 voip 应用的电量消耗。

基于这种类型的推送,开发者不必在后台设法维护一套长连接来保证接通率,客户端在收到推送的时候,会自动后台唤起应用,可以在此时完成云信相关的业务注册,展开正常的 voip 业务。开发者甚至可以在 PushKit 基础上, 借助 CallKit 搭建出一套呼叫界面,让应用拥有媲美原生来电通话的用户体验。

目前通过在云信后台配置 PushKit 证书,点对点电话呼叫接口推送将会使用 PushKit 。PushKit 证书配置与 APNS 证书配置雷同,这里不再展开。

在客户端实现中,需要将接口

- (void)registerWithAppID:(NSString *)appKey
                  cerName:(nullable NSString *)cerName

变更为

- (void)registerWithOption:(NIMSDKOption *)option

注册 PushKit 推送

PKPushRegistry *pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
pushRegistry.delegate = self;
pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];

在 PKPushRegistryDelegate 协议回调中,调用云信上传 PushKit Token 接口:

- (void)updatePushKitToken:(NSData *)token
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type
{
    if ([type isEqualToString:PKPushTypeVoIP])
    {
        [[NIMSDK sharedSDK] updatePushKitToken:credentials.token];
    }
}

推送问题排查方案

请参考云信IOS推送收不到问题排查方案

事件订阅 (在线状态)


云信允许用户订阅监听其他用户产生的事件,产生的事件的方式分为两种:

具体在线状态的业务逻辑可以参考 Demo 的 NTESSubscribeManager 实现。

发布自定义事件

@protocol NIMEventSubscribeManager <NSObject>
/**
 *  发布事件
 *
 *  @param event 需要广播的事件,事件可被其他人订阅
 *  @param completion 完成回调
 */
- (void)publishEvent:(NIMSubscribeEvent *)event
          completion:(NIMEventSubscribeBlock)completion;
@end

参数列表

参数 类型 说明
event NIMSubscribeEvent 需要广播的事件,事件可被其他人订阅
completion NIMEventSubscribeBlock 完成回调

在发布的前,需要自行构造出 NIMSubscribeEvent 对象,必须需要填写的字段为 type , valuetype 目前仅支持 “在线状态事件” , 即 NIMSubscribeSystemEventTypeOnline

NIMSubscribeEvent 对象原型

@interface NIMSubscribeEvent : NSObject

/**
 *  事件 Id, 发布时无需填写
 */
@property (nonatomic, copy, readonly) NSString *eventId;


/**
 *  事件发布者,发布时无须填写
 */
@property (nullable, nonatomic, copy, readonly) NSString *from;


/**
 *  事件发布的时间,发布时无须填写
 */
@property (nonatomic, assign, readonly) NSTimeInterval timestamp;


/**
 *  事件类型,1~99999 为云信保留类型,目前只支持预定义事件, 见 NIMSubscribeSystemEventType
 */
@property (nonatomic, assign) NSInteger type;


/**
 *  事件的状态值
 */
@property (nonatomic, assign) NSInteger value;


/**
 *  事件的有效期,范围为 60 秒到 7 天, 数值单位为秒,默认为 7 天
 */
@property (nonatomic, assign) NSTimeInterval expiry;


/**
 *  事件是否只广播给在线用户
 *  @discussion 默认为YES 如果这个值为NO,事件会在订阅者登录后同步
 */
@property (nonatomic, assign)  BOOL sendToOnlineUsersOnly;


/**
 *  事件是否支持多端同步
 *  @discussion 默认为YES。
 */
@property (nonatomic, assign)  BOOL syncEnabled;


/**
 *  订阅事件的额外信息,当订阅事件为 NIMSubscribeSystemEventTypeOnline 时,为 NIMSubscribeOnlineInfo
 */
@property (nonatomic, strong, readonly)  id subscribeInfo;

@end

属性列表

参数 类型 说明
eventId NSString 事件 Id, 发布时无需填写
from NSString 事件发布者,发布时无须填写
timestamp NSTimeInterval 事件发布的时间,发布时无须填写
from NSString 事件发布者,发布时无须填写
type NSInteger 事件类型,1~99999 为云信保留类型,目前只支持预定义事件, 见 NIMSubscribeSystemEventType
value NSInteger 事件的状态值
expiry NSTimeInterval 事件的有效期,范围为 60 秒到 7 天, 数值单位为秒,默认为 7 天
sendToOnlineUsersOnly BOOL 事件是否只广播给在线用户,默认为YES 如果这个值为NO,事件会在订阅者登录后同步
syncEnabled BOOL 事件是否支持多端同步, 默认为YES
subscribeInfo id 订阅事件的额外信息,当订阅事件为 NIMSubscribeSystemEventTypeOnline 时,为 NIMSubscribeOnlineInfo

订阅事件

@protocol NIMEventSubscribeManager <NSObject>
/**
 *  订阅事件
 *
 *  @param request 订阅请求
 *  @param completion 完成回调
 *  @discussion 请求中必需填写 type,expiry,publishers 字段
 */
- (void)subscribeEvent:(NIMSubscribeRequest *)request
            completion:(NIMEventSubscribeResponseBlock)completion;
@end

参数列表

参数 类型 说明
request NIMSubscribeRequest 订阅请求
completion NIMEventSubscribeResponseBlock 完成回调

取消订阅

@protocol NIMEventSubscribeManager <NSObject>
/**
 *  取消订阅事件
 *
 *  @param request 取消订阅请求
 *  @param completion 完成回调
 *  @discussion 请求中必须填写 type 字段 , 如果不填写 publishers 字段,则取消指定事件的全部订阅关系
 */
- (void)unSubscribeEvent:(NIMSubscribeRequest *)request
              completion:(NIMEventSubscribeResponseBlock)completion;
@end

参数列表

参数 类型 说明
request NIMSubscribeRequest 取消订阅请求
completion NIMEventSubscribeResponseBlock 完成回调

在调用 订阅/取消订阅 事件接口前,需要先构造 NIMSubscribeRequest 订阅请求对象。

NIMSubscribeRequest 原型

@interface NIMSubscribeRequest : NSObject

/**
 *  事件类型,1~99999 为云信保留类型,自定义的订阅事件请选择此范围以外的类型, 预定义事件定义见 NIMSubscribeSystemEventType
 */
@property (nonatomic, assign) NSInteger type;


/**
 *  订阅的有效期,范围为 60 秒到 30 天, 数值单位为秒, 超出时间则自动取消订阅,
 */
@property (nonatomic, assign) NSTimeInterval expiry;


/**
 *  订阅后是否立刻同步事件状态值
 *  @discussion 默认为NO,,如果填 YES ,则会收到事件回调 - (void)onRecvSubscribeEvent:
 */
@property (nonatomic, assign) BOOL syncEnabled;


/**
 *  发布事件者的 Id 数组,最多 100 个
 *  @discussion 由于同一个事件可能由不同的用户发出,只能订阅数组内用户发布的事件。
 */
@property (nonatomic, copy) NSArray *publishers;

@end

NIMSubscribeRequest 参数列表

参数 类型 说明
type NSInteger 事件类型,1~99999 为云信保留类型,自定义的订阅事件请选择此范围以外的类型, 预定义事件定义见 NIMSubscribeSystemEventType,可以使用自定义数值或者内置的枚举值
expiry NSTimeInterval 订阅的有效期,范围为 60 秒到 30 天, 数值单位为秒, 超出时间则自动取消订阅,
syncEnabled BOOL 订阅后是否立刻同步事件状态值,默认为NO,,如果填 YES ,则会收到事件回调 - (void)onRecvSubscribeEvent:
publishers NSArray 发布事件者的 Id 数组,最多 100 个,由于同一个事件可能由不同的用户发出,只能订阅数组内用户发布的事件。

在订阅事件中,订阅请求中必需填写 typeexpirypublishers 字段。publishers 字段最多仅支持 100 个账号 id , 某些场景如在线状态,订阅人数会超过限制,需要多次调用此接口来满足业务,具体详见 Demo 中 NTESSubscribeManager- (void)subscribeOnlineState 方法。

在取消订阅中,订阅请求中必须填写 type 字段,如果不填写 publishers 字段,则取消指定事件的全部订阅关系。

查询订阅事件关系

@protocol NIMEventSubscribeManager <NSObject>
/**
 *  查询订阅事件
 *
 *  @param request 查询请求
 *  @param completion 完成回调
 */
- (void)querySubscribeEvent:(NIMSubscribeRequest *)request
                 completion:(NIMEventSubscribeQueryBlock)completion;
@end

参数列表

参数 类型 说明
request NIMSubscribeRequest 取消订阅请求
completion NIMEventSubscribeQueryBlock 完成回调

SDK 提供查询本账号和指定账号存在的订阅关系接口,调用接口前,必须先构造 NIMSubscribeRequest 订阅请求对象。 其中,必须填写 type 字段 和 publishers 字段,查询人数最大支持 100 人。

目前不支持直接查询本账号和所有账号的订阅关系,上层需要维护好需要查询的用户 id, 通过多次调用此接口完成查询。

语音录制及播放


多媒体管理 NIMMediaManager 提供了音频播放、高清语音录制的功能。需要注意的是 NIM SDK 中的语音播放和录制仅支持 aac 和 amr,如果需要更多格式的支持,APP 需要自己实现,但并不推荐。

播放音频

@protocol NIMMediaManager <NSObject>
/**
 *  切换音频输出设备
 *
 *  @param outputDevice 音频输出设备
 *
 *  @return 是否切换成功
 */
- (BOOL)switchAudioOutputDevice:(NIMAudioOutputDevice)outputDevice
@end

NIMAudioOutputDevice 列表

参数 说明
NIMAudioOutputDeviceReceiver 0 听筒
NIMAudioOutputDeviceSpeaker 1 扬声器
@protocol NIMMediaManager <NSObject>
/**
 *  是否正在播放音频
 *
 */
- (BOOL)isPlaying
@end
@protocol NIMMediaManager <NSObject>
/**
 *  播放音频文件
 *
 *  @discussion 开始播放,NIMMediaManagerDelegate中的playAudio:didBeganWithError:回调会被触发,播放完成后, NIMMediaManagerDelegate中的playAudio:didCompletedWithError:回调会被触发
 *  @param filepath 音频文件路径
 */
- (void)play:(NSString *)filepath;
@end
参数 类型 说明
filepath NSString 音频文件路径

其中 filePath 为音频文件的路径,该操作会触发以下回调:

初始化工作完成,准备开始播放音频的时候会触发

@protocol NIMMediaManagerDelegate <NSObject>
/**
 *  开始播放音频的回调
 *
 *  @param filePath 音频文件路径
 *  @param error    错误信息
 */
- (void)playAudio:(NSString *)filePath didBeganWithError:(NSError *)error
@end

参数列表

参数 类型 说明
filepath NSString 音频文件路径
error NSError 错误信息

音频播放结束的时候会触发

@protocol NIMMediaManagerDelegate <NSObject>
/**
 *  录制音频完成后的回调
 *
 *  @param filePath 录制完成的音频文件路径
 *  @param error    错误信息
 */
- (void)playAudio:(NSString *)filePath didCompletedWithError:(NSError *)error
@end

参数列表

参数 类型 说明
filepath NSString 音频文件路径
error NSError 错误信息

音频播放结束的时候会触发

@protocol NIMMediaManager <NSObject>
/**
 *  停止播放音频
 *
 */
- (void)stopPlay
@end

该操作会触发回调:

@protocol NIMMediaManagerDelegate <NSObject>
/**
 *  录制音频完成后的回调
 *
 *  @param filePath 录制完成的音频文件路径
 *  @param error    错误信息
 */
- (void)playAudio:(NSString *)filePath didCompletedWithError:(NSError *)error
@end

录制音频

@protocol NIMMediaManager <NSObject>
/**
 *  是否正在录音
 *
 */
- (BOOL)isRecording
@end
@protocol NIMMediaManager <NSObject>
/**
 *  开始录制音频
 *
 *  @param duration 最长录音时间
 *  @discussion 开始录音,NIMMediaManagerDelegate中的recordAudio:didBeganWithError:回调会被触发,录音完成后, NIMMediaManagerDelgate中的recordAudio:didCompletedWithError:回调会被触发
 *              默认使用 aac 编码格式
 */
- (void)recordForDuration:(NSTimeInterval)duration;
@end

其中 duration 限制了录音的最大时长,该操作会触发以下回调:

初始化工作完成,准备开始录制的时候会触发

@protocol NIMMediaManagerDelegate <NSObject>
/**
 *  开始录制音频的回调
 *
 *  @param filePath 录制的音频的文件路径
 *  @param error    错误信息
 *  @discussion 如果录音失败,filePath 有可能为 nil
 */
- (void)recordAudio:(NSString *)filePath didBeganWithError:(NSError *)error
@end

当到录音时长达到设置的最大时长,或者手动停止录音会触发

@protocol NIMMediaManagerDelegate <NSObject>
/**
 *  录制音频完成后的回调
 *
 *  @param filePath 录制完成的音频文件路径
 *  @param error    错误信息
 */
- (void)recordAudio:(NSString *)filePath didCompletedWithError:(NSError *)error
@end

按照一定的时间间隔触发

@protocol NIMMediaManagerDelegate <NSObject>
/**
 *  音频录制进度更新回调
 *
 *  @param currentTime 当前录制的时间
 */
- (void)recordAudioProgress:(NSTimeInterval)currentTime
@end

其中 currentTime 为当前的录音时长,触发该回调的时间间隔可以通过以下属性设置,默认为 0.3 秒

@property (nonatomic, assign) NSTimeInterval recordProgressUpdateTimeInterval

@protocol NIMMediaManager <NSObject>
/**
 *  停止录制音频
 *
 *  @discussion 停止录音后NIMMediaManagerDelegate中的recordAudio:didCompletedWithError:回调会被触发
 */
- (void)stopRecord
@end

该操作会触发

@protocol NIMMediaManagerDelegate <NSObject>
/**
 *  录制音频完成后的回调
 *
 *  @param filePath 录制完成的音频文件路径
 *  @param error    错误信息
 */
- (void)recordAudio:(NSString *)filePath didCompletedWithError:(NSError *)error
@end
@protocol NIMMediaManager <NSObject>
/**
 *  取消录制音频
 *
 */
- (void)cancelRecord
@end

该操作会触发

@protocol NIMMediaManagerDelegate <NSObject>
/**
 *  录音被取消的回调
 */
- (void)recordAudioDidCancelled
@end

获取峰值

@protocol NIMMediaManager <NSObject>
/**
 *  获取录音分贝
 *
 */
- (float)recordPeakPower
@end

获取平均值

@protocol NIMMediaManager <NSObject>
/**
 *  获取录音分贝
 *
 */
- (float)recordAveragePower
@end

来电打断

@protocol NIMMediaManagerDelegate <NSObject>
/**
 *  播放音频开始被打断回调
 */
- (void)playAudioInterruptionBegin

/**
 *  录音开始被打断回调
 */
- (void)recordAudioInterruptionBegin
@end
@protocol NIMMediaManagerDelegate <NSObject>
/**
 *  播放音频结束被打断回调
 */
- (void)playAudioInterruptionEnd

/**
 *  录音结束被打断回调
 */
- (void)recordAudioInterruptionEnd
@end

智能对话机器人


智能对话机器人解决方案依托网易 IM 即时通讯、语音识别、语义理解等服务,为开发者提供人机交互API/SDK、语音识别、意图识别、知识库配置、动态接口等功能,可以在应用IM内快速集成场景丰富的智能对话机器人。

区别于开发者业务后台自行设定的机器人,网易波特中配置的机器人,类似网易精灵、小黄鸡这种通过配置知识库,与用户进行交流问答的智能对话机器人 。开发者可以在 网易波特服务 开通机器人服务。

机器人和云信账号是有绑定关系的,一个机器人账号对应了一个云信 id ,两者互相独立 , 云信内部负责维护对应关系。机器人所对应的云信用户不会在线,也不应该和其他正常用户有用户关系,如加好友,拉黑等。

智能对话机器人消息属于云信内置基础消息类型中的一种,发送示例请参考 发送消息 章节。

机器人内容格式规范可参考 机器人消息体模板说明

机器人的数据会在每次登录后自动同步至客户端。本地机器人数据由 NIMRobotManager 管理。机器人由 `` 表示。

NIMRobotManager 原型

@interface NIMRobot : NSObject

/**
 *  机器人对应的云信账号 Id
 */
@property (nullable,nonatomic,copy)   NSString    *userId;

/**
 *  机器人对应的波特 Id
 */
@property (nullable,nonatomic,copy,readonly) NSString *botId;

/**
 *  机器人昵称
 */
@property (nullable,nonatomic,copy,readonly) NSString *nickname;

/**
 *  机器人简介
 */
@property (nullable,nonatomic,copy,readonly) NSString *intro;

/**
 *  机器人头像
 */
@property (nullable,nonatomic,copy,readonly) NSString *avatarUrl;

/**
 *  机器人头像缩略图
 *  @discussion 仅适用于使用云信上传服务进行上传的资源,否则无效。
 */
@property (nullable,nonatomic,copy,readonly) NSString *thumbAvatarUrl;

@end

属性列表

参数 类型 说明
userId NSString 机器人对应的云信账号 Id
botId NSString 机器人对应的波特 Id
nickname NSString 机器人昵称
intro NSString 机器人简介
avatarUrl NSString 机器人头像
thumbAvatarUrl NSString 机器人头像缩略图,仅适用于使用云信上传服务进行上传的资源,否则无效。
@protocol NIMRobotManager <NSObject>
/**
 *  获取所有的机器人
 *  @return 所有机器人信息
 */
- (NSArray *)allRobots
@end
@protocol NIMRobotManager <NSObject>
/**
 *  是否是有效的机器人
 *
 *  @param userId 用户Id (机器人在云信的id)
 *  @return 是否是机器人
 */
- (BOOL)isValidRobot:(NSString *)userId
@end

当机器人被移除时,userId 对应的机器人则为无效。

@protocol NIMRobotManager <NSObject>
/**
 *  获取机器人信息
 *  @param userId 用户Id (机器人在云信的id)
 *  @return 机器人信息
 */
- (NIMRobot *)robotInfo:(NSString *)userId
@end

机器人消息

机器人消息分上行消息和下行消息。用户向机器人发送的消息被称为上行消息,构造示例可以参考发送消息 章节;机器人向用户回复的消息被称为下行消息。

在 NIMRobotObject 里,判断是否上下行的字段为

/**
 *  判断此消息是否是属于机器人回复的消息
 */
@property (nonatomic, assign, readonly) BOOL isFromRobot;

同时,设置了只有机器人下行消息才有效的只读字段:

/**
 *  机器人回复的消息所属的提问消息 Id ,只在机器人下行消息,此字段有效
 */
@property (nullable, nonatomic, copy, readonly) NSString *responseForMessageId
/**
 *  机器人回复的消息结果,只在机器人下行消息,此字段有效
 */
@property (nullable, nonatomic, copy, readonly) NSDictionary *response