转自:https://blog.csdn.net/sjl_leaf/article/details/77096296
便于记录查看地址,方便查找
网易云信/IM即时通讯/SDK开发集成/iOS开发集成
NIM SDK 使用指南
网易云信 SDK (NIM SDK) 为移动应用提供完善的 IM 开发框架,屏蔽其内部复杂细节,对外提供较为简洁的 API 接口,方便第三方应用快速集成 IM 功能。SDK 兼容 iOS 7.0+ ,Demo 兼容 iOS 8.0+ 。
NIM SDK 提供两种集成方式:您既可以通过 CocoaPods
自动集成我们的 SDK,也可以通过手动下载 SDK, 然后添加到您的项目中。
我们提供两个下载地址。分别为:
官网 SDK 下载入口。
我们提供了 GitHub 发布仓库 。NIMSDK,此仓库包含 IM 和音视频功能,您可以根据自己的需求选择下载。
根据自己工程需要,下载对应版本的 NIM SDK,得到 NIMSDK.framework 文件 ( 如果选择音视频版本,还将得到 NIMAVChat.framework 文件 ) ,以及未连接的全部三方依赖库 注1 ,将他们导入工程。
添加其他 NIM SDK 依赖库
注1 :开发者应根据自身项目,将不冲突的依赖库也添加进工程。
注2 :在 SDK 3.0.0 以前版本 (包括 3.0.0) ,c++ 库请使用 libstdc++6.0.9.tbd , 之后的版本统一替换成 libc++.tbd 。
在 Build Settings
-> Other Linker Flags
里,添加选项 -ObjC
。
在需要使用即时通讯 SDK 的地方 import
,在需要使用实时音视频 SDK 的地方 import
。
在 Podfile
文件中加入
pod 'NIMSDK'
安装
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
音视频网络探测管理类,提供音视频网络状态诊断功能在默认情况下,SDK 认为用户资料头像,群头像,聊天室类用户头像等信息都是默认托管在云信上,所以 SDK 会针对他们自动开启 HTTPS
支持,开发者不需要任何额外配置。
但如果开发者需要将这些信息都托管在自己的服务器上,需要在 NIMSDKConfig.h
中,将
@property (nonatomic,assign) BOOL enabledHttpsForInfo
@property (nonatomic,assign) BOOL enabledHttpsForMessage;
设置为 NO,避免 SDK 自动将开发者设置的 HTTP URL
自动转换为 HTTPS URL
。
因为苹果的 ATS 政策,如果应用中使用了 HTTP
请求,需要将工程配置文件中的 info.plist
文件,NSAppTransportSecurity
条目中适配好 NSExceptionDomains
。需要注意的是,2017 年以后,应用中存在 HTTP
请求会有审核被拒的风险。
。添加 SDK 初始化方法。
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NIMSDKOption *option = [NIMSDKOption optionWithAppKey:appKey];
option.apnsCername = // APNS 推送证书名
option.pkCername = //Pushkit 证书名
[[NIMSDK sharedSDK] registerWithOption:option];
return YES;
}
推荐在 APP 启动时尽快注册 NIM SDK。
在使用 SDK 之前,需要对云信的体系流程有基本的认知,推荐开发者首先阅读这里 。
调用
[[[NIMSDK sharedSDK] loginManager] login:account
token:token
completion:^(NSError *error) {}];
error为登录错误信息,成功则为nil。不要在登录完成的回调中直接获取 SDK 缓存数据,而应该在 同步完成的回调里获取数据 或者 监听相应的数据变动回调后获取 。
注:在不特殊说明的情况下,SDK 的所有回调都是在主线程中发起,无论是以 block 还是 delegate 的形式,也推荐开发者仅在主线程调用 SDK 相关接口。
获取登录帐号的云信 id:
NSString *userID = [NIMSDK sharedSDK].loginManager.currentAccount;
SDK 不支持直接添加网易云通信用户,请参考服务端API文档 的 创建网易云通信 ID 章节,在您的应用服务器上使用 Http 接口进行添加。
NIM SDK 有两种自动登录的场景:
1.SDK 发起的自动登录:登录完毕后因网络发生切换,断网等情况发生而需要重连,SDK 将自动进行重连重登,无需 APP 干预。
2.APP 发起的自动登录:APP 启动时,如果已保存用户名和密码可以选择调用自动登录接口,并立刻打开主界面。此时 APP 可以在无网络,未登录成功的状态下直接访问用户本地数据。
//APP主动发起自动登录
- (void)autoLogin:(NIMAutoLoginData *)loginData
NIMAutoLoginData
中的 forcedMode
为强制模式开关。非强制模式下的自动登录,服务器将检查当前登录设备是否为上一次登录设备,如果不是,服务器将拒绝这次自动登录(返回 error code 为 417 的错误);强制模式下的自动登录,服务器将不检查当前登录设备是否为上一次登录设备,安全性较低,但较为便捷。
和手动登录不同,自动登录通过委托通知登录状态。 APP 需要实现如下回调 (手动登录也会收到同样的委托回调)
- (void)onLogin:(NIMLoginStep)step
自动登录过程不需要 APP 加以干预,SDK 会在有网络的情况下有策略地不断重试直到登录为止。但下面两种异常情况需要 APP 处理:被踢和特殊的登录错误。
-(void)onKick:(NIMKickReason)code
clientType:(NIMLoginClientType)clientType
APP收到被踢回调后需要进行注销并切换到登录界面。
- (void)onAutoLoginFailed:(NSError *)error
大部分自动登录回调错误 APP 并不需要关心,只需注意如下几种情况:
1.用户名密码错误导致自动登录失败,error code 为 302。这种情况一般发生于用户在其他设备上修改了密码。
2.已有一端登录导致自动登录失败,error code 为 417。这种情况发生于非强制登录模式下已有一端在线而当前设备进行自动登录(设置为只允许一端同时登录时),出于安全方面的考虑,云信服务器判定当前端需要重新手动输入用户密码进行登录,故拒绝登录。
3.NIMSDKConfig
设置了 maxAutoLoginRetryTimes
属性,即 App 设定当前 SDK 自动登录失败的重试次数,那么在当前会话中如果登录出错超过预定次数,将抛出 code 为 NIMLocalErrorCodeAutoLoginRetryLimit
的本地错误
一旦发生如上情况,APP 同样需要进行额外处理:注销或重试。
调用
[[[NIMSDK sharedSDK] loginManager] logout:^(NSError *error){}];
应用层登出/注销自己的账号时需要调用 SDK 的登出操作,该操作会通知云信服务器进行 APNS 推送信息的解绑操作,避免用户已登出但推送依然发送到当前设备的情况发生。
考虑到用户体验,登出的超时时间会比其他请求短一些。上层应用不管登出请求是否成功,UI 表现上都应该做出登出行为。
当用户在某个客户端登录时,其他没有被踢掉的端会触发回调:
- (void)onMultiLoginClientsChanged;
同时,可以查询当前时间登录的设备列表:
- (NSArray *)currentLoginClients;
云信内置踢人策略为:移动端(Android,iOS)互踢,桌面端(PC,Web)互踢,移动端和桌面端共存。
如果当前的互踢策略无法满足业务需求的话,可以联系我们取消内置互踢,根据多端登录的回调和当前的设备列表,判断本设备是否需要被踢出。如果需要踢出,直接调用登出接口并在界面上给出相关提示即可。
NIM SDK 的登录一共有大约十个步骤,包括正在连接,连接成功,正在登录等。详见 NIMLoginStep 枚举。其中重要的两个步骤为:登录成功 (NIMLoginStepLoginOK) 和 同步成功 (NIMLoginStepSyncOK)。
NIM SDK 在登录后会同步群信息,离线消息,漫游消息,系统通知等数据。
SDK 中用户与同一个对象的聊天信息集合,称为一个会话,用 NIMSession
来表示。会话有单人会话,群组会话,聊天室会话等类型。
SDK 中用于表示消息的结构为 NIMMessage
,目前提供如下几种消息类型,不同的消息类型对应不同的 MessageObject
消息格式 | MessageObject |
---|---|
文本消息 | nil |
图片消息 | NIMImageObject |
音频消息 | NIMAudioObject |
视频消息 | NIMVideoObject |
文件消息 | NIMFileObject |
地理位置消息 | NIMLocationObject |
通知消息 | NIMNotificationObject |
提醒消息 | NIMTipObject |
自定义消息 | NIMCustomObject |
消息 NIMMessage
定义了一些额外的状态属性,推荐只在主线程对这些属性进行读写:
消息的接收状态 isReceivedMsg
由于漫游消息的存在,所以自己发出的消息漫游下来后仍旧是 收到的消息 ,这个字段用于消息出错时,判断需要重发还是重收。
消息的排版状态 isOutgoingMsg
用于鉴别是否为发出去的消息。用户可以选择和自己发起对话,所以并不是所有来源是自己的消息都是往外发的消息,这个字段主要用于判断头像排版位置,往外发的消息气泡放右边,其他消息气泡放左边。
消息的投递状态 deliveryState
此状态仅对发送的消息有效。消息的投递状态有 发送中 , 发送失败 , 发送成功 三种。
消息附件的下载状态 attachmentDownloadState
此状态仅对收到的且带有附件的消息有效。 下载状态有 下载失败 , 下载中 , 下载成功 三种。
消息的删除状态 isDeleted
消息是否标记为已删除,已删除的消息在获取本地消息列表时会被过滤掉,只有根据messageId获取消息的接口可能会返回已删除消息。
消息的播放状态 isPlayed
用于鉴别音频类的消息是否播放过。 上层应用可以根据业务修改这个属性。注意不要频繁修改这个属性值,每次对这个属性做出修改,就会自动更新一次数据库。
消息服务器扩展字段 remoteExt
此字段会发送到其他端,上层需要保证 NSDictionary 可以转换为 JSON。
消息本地扩展字段 localExt
此字段只在本地存储,不会发送至对端,上层需要保证 NSDictionary 可以转换为 JSON。
消息发送方的显示名 senderName
服务器内置的消息发送者名字,当发送者是自己时,这个值为空。在本地没法获取到相应发送者信息时推荐时使用这个值。
对端已读 isRemoteRead
接收对端已读回执后,所有小于已读回执时间戳的消息都会被置为 对端已读 。
1.构造并发送消息
//构造消息
NIMMessage *message = [[NIMMessage alloc] init];
message.text = text;
//构造会话
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];
//发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
//构造消息
NIMImageObject * imageObject = [[NIMImageObject alloc] initWithImage:image];
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = imageObject;
//构造会话
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];
//发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
//构造消息
NIMAudioObject *audioObject = [[NIMAudioObject alloc] initWithSourcePath:filePath];
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = audioObject;
//构造会话
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];
//发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
//构造消息
NIMVideoObject *videoObject = [[NIMVideoObject alloc] initWithSourcePath:filePath];
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = videoObject;
//构造会话
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];
//发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
//构造消息
//其中,latitude为纬度,longitude为经度,title为位置的描述字段
NIMLocationObject *locationObject = [[NIMLocationObject alloc] initWithLatitude:latitude Longitude:longitude address:title];
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = locationObject;
//构造会话
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];
//发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
//构造消息
//其中,path 为文件保存路径
NIMFileObject *fileObject = [[NIMFileObject alloc] initWithSourcePath:path];
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = fileObject;
//构造会话
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];
//发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
//要在界面上显示的消息
message.text = @"hi @robot, hello robot";
//真正和机器人对话的消息
NSString *content = @"hello robot";
//构造机器人消息附件
NIMRobotObject *object = [[NIMRobotObject alloc] initWithRobot:content robotId:robotId];
message.messageObject = object;
//构造会话
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];
//发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
//要在界面上显示的消息
message.text = @"hi @robot, plan A";
//具体跳转的模板 target
NSString *target = @"targetID";
//具体跳转参数
NSString *params = @"params";
//构造机器人消息附件
NIMRobotObject *object = [[NIMRobotObject alloc] initWithRobotId:robotId target:target param:params];
message.messageObject = object;
//构造会话
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];
//发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
通知消息
一些特定场景的行为,云信服务器预置了一些通知消息。通知消息也是一种特定消息,开发者需要解析消息中附带的信息,来获取通知内容,具体步骤为:
NIMMessage
中的 messageObject
字段,强类型转换为 NIMNotificationObject
。NIMNotificationObject
中的 content
字段,得到父类 NIMNotificationContent
。NIMNotificationContent
中的 notificationType
字段,将父类 NIMNotificationContent
强类型转化成具体子类型。 所有 content
类型如下:通知类型 | NIMNotificationContent |
---|---|
群通知 | NIMTeamNotificationContent |
网络电话通知 | NIMNetCallNotificationContent |
聊天室通知 | NIMChatroomNotificationContent |
未被支持类型通知 | NIMUnsupportedNotificationContent |
由于系统升级,旧版本的 SDK 可能无法解析新版本数据,所有无法解析的新通知显示为未被支持。
当不需要一些通知时,开发者可以实现 NIMSDKConfig
的委托 delegate
,来控制哪些通知需要忽略。
- (BOOL)shouldIgnoreNotification:(NIMNotificationObject *)notification
当消息将要存储到本地时,会调用此回调,开发者只应该在这个回调里做简单逻辑判断,如果做耗时操作会严重影响存储性能。
不支持从客户端发出通知消息。
提醒消息
提醒消息用于会话内的状态提醒,如进入会话时出现的欢迎消息,会话命中敏感词后的提示消息等。
//构造消息
NIMTipObject *tipObject = [[NIMTipObject alloc];
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = tipObject;
//构造会话
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];
//发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
自定义消息用于 APP 拓展自己的消息类型,实现不同业务逻辑。自定义消息的 MessageObject(NIMCustomObject) 仅有一个 id 字段,SDK 会负责透传这个对象序列化后的结果。NIMCustomAttachment 协议包括一个必须实现的序列化接口和三个与上传相关的可选接口。如果需要在自定义消息中上传文件作为附件的一部分,必须实现这三个上传接口,缺一不可。实现自定义消息参考教程。
//构造消息
NIMCustomObject *customObject = [[NIMCustomObject alloc] init];
customObject.attachment = attachment;
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = customObject;
//构造会话
NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P];
//发送消息
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil];
2.检查调用状态
正常情况这一步可以省略,但刚开始集成 SDK 时,因为上层开发对 API 不熟悉有可能传入一些无效参数,推荐在开发前期务必检查 sendMessage:toSession:error 的返回值和 error 信息,并以此为依据排查问题。
3.处理回调
在调用完发送消息接口后,通常会收到如下回调
- (void)willSendMessage:(NIMMessage *)message
建议开发者仅在收到这个回调后才将消息加入显示用的数据源中。
- (void)sendMessage:(NIMMessage *)message
progress:(CGFloat)progress
图片,视频等需要上传附件的消息会有比较详细的进度回调,文本消息则没有这个回调。
- (void)sendMessage:(NIMMessage *)message
didCompleteWithError:(NSError *)error
如果消息发送成功 error 为 nil,反之 error 会被填充具体的失败原因。
4.重发
因为网络原因等导致的发送消息失败而需要重发的情况,直接调用
- (BOOL)resendMessage:(NIMMessage *)message
error:(NSError **)error
此时如果再次调用 sendMessage,则会被 NIM SDK 认作新消息。
5.消息的发送设置
SDK 提供消息发送设置来满足开发者的对服务器自定义需求,这些设置可以在 NIMMessage
的 NIMMessageSetting
属性中找到。
消息允许在消息历史中拉取开关 historyEnabled
默认为 YES 。正常而言所有消息都会出现在通过 NIMConversationManager
调用( fetchMessageHistory:option:result:
)返回的结果中,但是可以通过设置这个值来使得消息不出现在这其中。
消息支持漫游开关 roamingEnabled
默认为 YES 。 消息漫游的概念是指一定时间内发送的消息可以在另一端被同步到,以保证最大限度的消息同步。(如 iOS 上收发的消息过了一天登录 PC 仍旧会收到,这种消息我们称之为漫游消息)
消息支持多端同步开关 syncEnabled
默认为 YES 。在默认情况下,如果用户在 iOS 端和其他端(如 PC )同时登录一个帐号,那么 iOS 端发送的消息会被同步到其他端,同样其他端发送的消息也会被同步到 iOS 端。但是需要注意的是因为 iOS 经常会退到后台,所以其他端发送的消息在 iOS 断线后是通过漫游消息来同步到的。
消息被计入未读开关 shouldBeCounted
默认为 YES 。默认情况下,用户收到的所有消息都会被计入未读。设置这个为 NO 后,对应的消息被对端接受后将不计入未读消息计数内。本地写消息时,也可以用这个字段配置写入后是否计入未读。
消息需要被推送开关 apnsEnabled
默认为YES。设置这个为NO后,消息将不再有苹果推送通知。
消息推送前缀开关(一般为昵称) apnsWithPrefix
默认为YES。将这个字段设为NO,推送消息将不带有前缀,如推送消息 “ 小明:今天吃什么? ” 中的 “ 小明:” 将被省略。
消息是否需要抄送 routeEnabled
默认为YES。将这个字段设为NO, 则不会抄送此消息给开发者的服务器(如果有配置的话)
chatManager
的回调函数通知上层- (void)onRecvMessages:(NSArray *)messages
如果收到的是图片,视频等需要下载附件的消息,在回调的处理中还需要调用
(SDK 默认会在第一次收到消息时自动调用)
- (BOOL)fetchMessageAttachment:(NIMMessage *)message
error:(NSError **)error
进行附件的下载,附件的下载过程会通过
- (void)fetchMessageAttachment:(NIMMessage *)message
progress:(CGFloat)progress
- (void)fetchMessageAttachment:(NIMMessage *)message
didCompleteWithError:(NSError *)error;
这两个回调返回进度和结果。
除了 通知消息 之外,其他类型消息均支持转发给其他会话。
- (BOOL)forwardMessage:(NIMMessage *)message
toSession:(NIMSession *)session
error:(NSError **)error
这里返回的 error
参数只是表示当前这个函数调用是否成功,需要后续的回调才能够判断消息是否已经发送至服务器。后续回调和普通消息发送流程相同。
在会话界面中调用发送已读回执的接口并传入最后一条消息,即表示这之前的消息都已读,对端将收到此回执。
发送已读回执
- (void)sendMessageReceipt:(NIMMessageReceipt *)receipt
completion:(NIMSendMessageReceiptBlock)completion;
接受已读回执
- (void)onRecvMessageReceipt:(NIMMessageReceipt *)receipt;
在发送端 NIMMessageReceipt
需要通过最后一条消息 NIMMessage
进行初始化并进行发送,而接收端可以通过 NIMMessageReceipt
中的 timestamp
来得知发送端当前已读时间戳。此功能仅在 P2P
消息中有效。重复发送和通过无效消息构造的已读回执都将被 SDK 忽略。
在会话时,允许用户撤回一定时间内发送过的消息。
- (void)revokeMessage:(NIMMessage *)message
completion:(NIMRevokeMessageBlock)completion;
在撤回消息请求调用成功后, SDK 会先回调给上层成功,再自动将本地的这条消息删除。如果需要在撤回后显示一条已撤回的提示 ( 见 Demo 交互 ) ,开发者可以自行构造一条提醒消息并插入本地数据库。
以下情况消息撤回会失败
当有消息撤回发生时,被撤回方 SDK 会触发回调:
- (void)onRecvRevokeMessageNotification:(NIMRevokeMessageNotification *)notification
SDK 在收到消息撤回后,会先从本地数据库中找到对应消息并进行删除,之后通知上层消息已删除。如果需要在撤回后显示一条已撤回的提示 ( 见 Demo 交互 ) ,开发者在这个回调中自行构造一条提醒消息并插入本地数据库。
由于用户业务场景不一致,在撤回后可能在撤回后用一条提醒消息替代,也有可能不做任何提示,而被撤回的消息本身可能是未读的,这样不同的业务逻辑就造成了未读数的不一致。 在 NIMSDKConfig.h
中统一封装了撤回未读配置 接口:
@property (nonatomic,assign) BOOL shouldConsiderRevokedMessageUnreadCount;
默认为 NO。设置成 YES 的情况下,如果被撤回的消息本地还未读,那么当消息发生撤回时,对应会话的未读计数将减 1 以保持最近会话未读数的一致性。 当不做任何提示时,可以设置为 YES,以保持未读计数的一致性。
NIMConversationManager
提供最近消息的本地存储管理功能。
最近会话 NIMRecentSession
用于表示会话列表页的数据模型。当用户发送,收取及删除消息时,都会同时去修改最近会话。
当收到或者一条消息时,会自动生成这个消息对应的最近会话。但值得注意的是最近会话和会话并不是一一对应的关系,删除最近会话并不会影响会话。
- (NSArray *)allRecentSessions
NIMConversationManager
提供了最近会话的三个回调通知上层:
分别为增加,修改,删除最近会话的回调:
- (void)didAddRecentSession:(NIMRecentSession *)recentSession
totalUnreadCount:(NSInteger)totalUnreadCount
- (void)didUpdateRecentSession:(NIMRecentSession *)recentSession
totalUnreadCount:(NSInteger)totalUnreadCount
- (void)didRemoveRecentSession:(NIMRecentSession *)recentSession
totalUnreadCount:(NSInteger)totalUnreadCount
开发者无法自己添加最近消息,最近消息会在发送或者收到消息的时候自动添加,并触发增加最近会话的回调。
单条消息的删除
- (void)deleteMessage:(NIMMessage *)message;
调用此方法时,如果删除的是最后一条消息,消息所属的最近会话的 lastMessage 属性会自动变成上一条消息(没有则为空消息),同时触发最近消息修改的回调。
单个会话批量消息删除
- (void)deleteAllmessagesInSession:(NIMSession *)session
removeRecentSession:(BOOL)removeRecentSession
removeRecentSession
标记了最近会话是否会被保留,会话内消息将会标记为已删除。调用此方法会触发最近消息修改的回调,如果选择保留最近会话, lastMessage
属性将会被置成一条空消息。
- (void)deleteRecentSession:(NIMRecentSession *)recentSession
只会删除最近会话,但保留会话内消息。调用时,总未读消息数会减去当前会话的未读数。调用此方法触发最近消息删除的回调。
- (void)deleteAllMessages:(BOOL)removeRecentSessions
removeRecentSession
标记了最近会话是否会被保留。调用这个接口只会触发 - (void)allMessagesDeleted
回调,其他针对单个 recentSession 的回调都不会被调用。
- (NSInteger)allUnreadCount
- (void)markAllMessagesReadInSession:(NIMSession *)session
调用这个方法时,会将所有属于这个会话的消息都置为已读状态。相应的最近会话(如果有的话)未读数会自动置 0 并且触发最近消息修改的回调
最近会话提供本地扩展能力,可以用来开发 @
以及 置顶
等功能。
开发者可以通过 RecentSession
的 localExt
接口读取扩展。
并通过调用 NIMConversationManager
修改本地扩展信息
- (void)updateRecentLocalExt:(NSDictionary *)ext
recentSession:(NIMRecentSession *)recentSession
NIMConversationManager
支持从云信服务器上远程获取之前的聊天历史记录。
- (void)fetchMessageHistory:(NIMSession *)session
option:(NIMHistoryMessageSearchOption *)option
result:(NIMFetchMessageHistoryBlock)block;
其中 option 为搜索选项,具体选项如下:
NIMConversationManager
支持本地查询消息
- (NSArray
message:(NIMMessage *)message
limit:(NSInteger)limit;
传入一个已知的消息,返回比这个消息更早的消息集合。如果没有已知的消息,则传入 nil,返回最新的消息集合。
NIMConversationManager
支持按消息 id 查询消息,可以查出被删除的消息。
- (NSArray
messageIds:(NSArray
NIMConversationManager
支持根据会话搜索本地历史消息
- (void)searchMessages:(NIMSession *)session
option:(NIMMessageSearchOption *)option
result:(NIMSearchMessageBlock)block;
以及搜索本地全局历史消息
- (void)searchAllMessages:(NIMMessageSearchOption *)option
result:(NIMGlobalSearchMessageBlock)result
其中 option 为搜索选项,具体选项如下:
搜索方向: 正向或反向查询消息历史。
搜索条数: 搜索的范围由 startTime , endTime 和 limit 参数共同限制。limit 为非零整数。
消息类型: 需要搜索的消息类型。
匹配内容: 如果需要搜索的消息类型为文本,会进行内容的匹配。
是否是全消息类型:默认为 NO,当设置为 YES 时,忽略 messageType 和 searchContent,同时返回所有的消息类型消息。
消息发起者列表。
搜索将返回:时间在 (startTime,endTime) 之间,消息类型为指定类型,且匹配搜索内容或消息发起者列表的一定数量的消息。
多媒体管理 NIMMediaManager
提供了音频播放、高清语音录制的功能。需要注意的是 NIM SDK 中的语音播放和录制仅支持 aac 和 amr,如果需要更多格式的支持,APP 需要自己实现,但并不推荐。
- (BOOL)switchAudioOutputDevice:(NIMAudioOutputDevice)outputDevice
- (BOOL)isPlaying
- (void)play:(NSString *)filepath;
其中 filePath
为音频文件的路径,该操作会触发以下回调:
初始化工作完成,准备开始播放音频的时候会触发
- (void)playAudio:(NSString *)filePath didBeganWithError:(NSError *)error
音频播放结束的时候会触发
- (void)playAudio:(NSString *)filePath didCompletedWithError:(NSError *)error
- (void)stopPlay
该操作会触发回调:
- (void)playAudio:(NSString *)filePath didCompletedWithError:(NSError *)error
- (BOOL)isRecording
- (void)recordForDuration:(NSTimeInterval)duration;
其中 duration
限制了录音的最大时长,该操作会触发以下回调:
初始化工作完成,准备开始录制的时候会触发
- (void)recordAudio:(NSString *)filePath didBeganWithError:(NSError *)error
当到录音时长达到设置的最大时长,或者手动停止录音会触发
- (void)recordAudio:(NSString *)filePath didCompletedWithError:(NSError *)error
按照一定的时间间隔触发
- (void)recordAudioProgress:(NSTimeInterval)currentTime
其中 currentTime
为当前的录音时长,触发该回调的时间间隔可以通过以下属性设置,默认为 0.3 秒
@property (nonatomic, assign) NSTimeInterval recordProgressUpdateTimeInterval
- (void)stopRecord
该操作会触发
- (void)recordAudio:(NSString *)filePath didCompletedWithError:(NSError *)error
- (void)cancelRecord
该操作会触发
- (void)recordAudioDidCancelled
获取峰值
- (float)recordPeakPower
获取平均值
- (float)recordAveragePower
- (void)playAudioInterruptionBegin
- (void)recordAudioInterruptionBegin
- (void)playAudioInterruptionEnd
- (void)recordAudioInterruptionEnd
群组功能对应的管理类为 NIMTeamManager
。NIMTeamManager
提供了普通群 (Normal) 以及高级群 (Advanced) 两种形式的群聊功能。高级群拥有更多的权限操作,两种群聊形式在共有操作上保持了接口一致。推荐 APP 开发时只选择一种群类型进行开发。普通群和高级群在原则上是不能互相转换的,他们的群类型在创建时就已经确定。在 SDK 2.4.0
版本后,高级群可以拥有普通群的全部功能,推荐使用高级群进行开发。
开发手册中所提及的普通群都等同于 Demo 中的讨论组。普通群没有权限操作,适用于快速创建多人会话的场景。每个普通群只有一个管理员。管理员可以对群进行增减员操作,普通成员只能对群进行增员操作。在添加新成员的时候,并不需要经过对方同意。
高级群在权限上有更多的限制,权限分为群主、管理员、以及群成员。
NIM SDK 在程序启动时会对本地群信息进行同步,所以只需要调用本地缓存接口获取群就可以了。 SDK 提供了批量获取自己的群接口、以及根据单个群 id 查询的接口。同样 SDK 也提供了远程获取群信息的接口。
本地获取
- (NSArray
- (NIMTeam *)teamById:(NSString *)teamId
远程获取
- (void)fetchTeamInfo:(NSString *)teamId
completion:(NIMTeamFetchInfoHandler)block;
- (void)createTeam:(NIMCreateTeamOption *)option
users:(NSArray
completion:(NIMTeamCreateHandler)completion
option 提供以下创建群选项
创建群类别,普通群或者高级群
群名称
群头像
群介绍
群公告
群验证方式
邀请群成员
邀请附言
被邀请人验证方式
谁可以邀请其他人入群 (默认群主管理员)
谁可以修改群资料 (默认群主管理员)
谁可以修改群自定义属性(默认群主管理员)
用户可以通过被动接受邀请和主动加入两种方式进入群组。
邀请用户入群
- (void)addUsers:(NSArray
toTeam:(NSString *)teamId
postscript:(NSString *)postscript
completion:(NIMTeamMemberHandler)completion
请求完成后,如果是普通群,被邀请者将直接入群;如果是高级群,云信服务器会下发一条系统消息到目标用户,目标用户可以选择同意或者拒绝入群。
同意群邀请(仅限高级群)
- (void)acceptInviteWithTeam:(NSString*)teamId
invitorId:(NSString*)invitorId
completion:(NIMTeamHandler)block
拒绝群邀请(仅限高级群)
- (void)rejectInviteWithTeam:(NSString*)teamId
invitorId:(NSString*)invitorId
rejectReason:(NSString*)rejectReason
completion:(NIMTeamHandler)block
主动申请入群(仅限高级群)
- (void)applyToTeam:(NSString *)teamId
message:(NSString *)message
completion:(NIMTeamApplyHandler)block
请求完成后,云信服务器会下发一条系统消息给群管理员,管理员可以选择通过或者拒绝申请。
通过申请(仅限高级群)
- (void)passApplyToTeam:(NSString *)teamId
userId:(NSString *)userId
completion:(NIMTeamApplyHandler)block
拒绝申请(仅限高级群)
- (void)rejectApplyToTeam:(NSString *)teamId
userId:(NSString *)userId
rejectReason:(NSString *)rejectReason
completion:(NIMTeamHandler)block
普通成员可以修改自己的群资料,管理员以上权限的群成员可以修改他人群资料以及群组信息。包括:
修改群成员昵称
- (void)updateUserNick:(NSString *)userId
newNick:(NSString *)newNick
inTeam:(NSString *)teamId
completion:(NIMTeamHandler)block
修改群名称
- (void)updateTeamName:(NSString *)teamName
teamId:(NSString *)teamId
completion:(NIMTeamHandler)block
修改群头像
- (void)updateTeamAvatar:(NSString *)teamAvatarUrl
teamId:(NSString *)teamId
completion:(NIMTeamHandler) block
修改群介绍
- (void)updateTeamIntro:(NSString *)intro
teamId:(NSString *)teamId
completion:(NIMTeamHandler)block
修改群公告
- (void)updateTeamAnnouncement:(NSString *)announcement
teamId:(NSString *)teamId
completion:(NIMTeamHandler)block
修改群验证方式
- (void)updateTeamJoinMode:(NIMTeamJoinMode)joinMode
teamId:(NSString *)teamId
completion:(NIMTeamHandler)block
修改被邀请人验证方式
- (void)updateTeamBeInviteMode:(NIMTeamBeInviteMode)beInviteMode
teamId:(NSString *)teamId
completion:(NIMTeamHandler)block;
修改谁可以邀请其他人入群
- (void)updateTeamInviteMode:(NIMTeamInviteMode)inviteMode
teamId:(NSString *)teamId
completion:(NIMTeamHandler)block
修改谁可以修改群资料
- (void)updateTeamUpdateInfoMode:(NIMTeamUpdateInfoMode)updateInfoMode
teamId:(NSString *)teamId
completion:(NIMTeamHandler)block
修改谁可以修改群自定义属性
- (void)updateTeamUpdateClientCustomMode:(NIMTeamUpdateClientCustomMode)clientCustomMode
teamId:(NSString *)teamId
completion:(NIMTeamHandler)block
高级群群主可以对群进行权限管理,权限管理包括:
提升管理员
- (void)addManagersToTeam:(NSString *)teamId
users:(NSArray
completion:(NIMTeamHandler)completion
移除管理员
- (void)removeManagersFromTeam:(NSString *)teamId
users:(NSArray
completion:(NIMTeamHandler)completion
转让群
- (void)transferManagerWithTeam:(NSString *)teamId
newOwnerId:(NSString *)newOwnerId
isLeave:(BOOL)isLeave
completion:(NIMTeamHandler)block
获取群成员
- (void)fetchTeamMembers:(NSString *)teamId
completion:(NIMTeamMemberHandler)block
获取到的群成员只有云信服务器托管的群相关数据,需要开发者结合自己管理的用户数据进行界面显示。
修改自己的群成员自定义属性
- (void)updateMyCustomInfo:(NSString *)newInfo
inTeam:(NSString *)teamId
completion:(NIMTeamHandler)block
修改后,其他在线用户自动同步获得修改后的属性。
用户退群
- (void)quitTeam:(NSString *)teamId
completion:(NIMTeamHandler)block
用户退群成功后,相关会话信息仍然会保留,但不再能接收关于此群的消息。
禁言用户
- (void)updateMuteState:(BOOL)mute
userId:(NSString *)userId
inTeam:(NSString *)teamId
completion:(NIMTeamHandler)block
禁言用户后,云信服务器会下发一条提示该用户被禁言的群组通知消息。
踢出用户
- (void)kickUsers:(NSArray
fromTeam:(NSString *)teamId
completion:(NIMTeamHandler)completion
被踢出的用户相关会话信息仍然会保留,但不再能接收关于此群的消息。
- (void)dismissTeam:(NSString*)teamId
completion:(NIMTeamHandler)block
群解散后,所有群用户关于此群会话会被保留,但是不能能够在此群会话里收发消息。
用户的群信息会在以下条件下更新:
这些操作成功后,云信服务器会推送一条群通知,同时触发 SDK 更新群信息的委托事件:
- (void)onTeamUpdated:(NIMTeam *)team
用户的群信息会在以下条件下移除:
这些操作成功后,云信服务器同样会推送一条群通知,同时触发 SDK 更新群信息的委托事件:
- (void)onTeamRemoved:(NIMTeam *)team
用户的群成员信息会在以下条件下更新
这些操作成功后,云信服务器同样会推送一条群通知,同时触发 SDK 更新群信息的委托事件:
- (void)onTeamMemberChanged:(NIMTeam *)team;
群组通知是一种消息类型 ( NIMMessageTypeNotification
) ,用户在创建群或者进入群成功之后,任何关于群的变动,云信服务器都会下发一条群通知消息。群通知消息和其他消息一样,可从 NIMConversationManager
提供的消息查询接口中获取。
群组通知解析步骤:
NIMMessage
中的 messageObject
字段,强类型转换为 NIMNotificationObject
。NIMNotificationObject
中的 content
字段,得到父类 NIMNotificationContent
。NIMNotificationContent
中的 notificationType
字段,将父类 NIMNotificationContent
强类型转化为 NIMTeamNotificationContent
。群组通知的具体类型可以通过 NIMTeamNotificationContent
的 operationType
解析。
SDK 在收到群通知之后,会对本地缓存的群信息做出对应的修改,然后触发与修改相对应的委托事件回调。
群通知是接收型的消息,开发者不应该自己手动去创建和发送群通知消息。
群组通知内容 NIMTeamNotificationContent
的字段说明:
operationType
: 群组通知事件类型,表示具体属于哪一种群组通知,通知种类由 NIMTeamOperationType
枚举定义。source
: 通知的操作者 ID ,表示谁触发了这个通知。targets
: 通知的被操作者 ID 列表,表示这个通知影响的用户群体。notifyExt
: 通知的扩展字段,这个扩展字段是由每个触发通知的操作接口定义的。目前只能由服务器的操作接口去定义这个字段。
例如:
群组踢出用户,可以调用服务器 HTTP 接口,并传入通知扩展参数。调用后会触发用户被踢出群组的事件消息通知,此时,收到消息的其他群成员就可以通过读取 `NIMTeamNotificationContent` 的 `notifyExt` 字段来获取踢出时定义的扩展字段。
attachment
: 有些通知比较复杂,需要一些额外信息来辅助上层显示,目前有额外信息的群通知类型为:
NIMUpdateTeamInfoAttachment
类型。NIMMuteTeamMemberAttachment
类型。SDK 提供了修改群消息通知的接口,上层可以通过设置这个选项以影响群消息的通知行为。当设置 notify 为 NO 时,群内消息将不会有 APNS 通知。当然上层也可以使用这一属性来决定收到在线消息时的 APP 表现 (是否响铃等)。
- (void)updateNotifyState:(BOOL)notify
inTeam:(NSString *)teamId
completion:(NIMTeamHandler)block;
群组允许管理员将部分成员禁言,或者全体禁言。禁言属于高级功能,需要调用云信服务器接口,客户端 SDK 仅提供查询功能。
查询禁言用户列表
- (void)fetchTeamMutedMembers:(NSString *)teamId
completion:(nullable NIMTeamMemberHandler)completion;
绝大多数情况这个请求都是从本地读取缓存并同步返回,但是由于群成员信息量较大, SDK 采取的是登录后延迟拉取的策略。
考虑到用户网络等问题, SDK 有可能没有及时缓存群成员信息,那么这个请求将是个带网络请求的异步操作(增量请求)。
同时这个接口会去请求本地没有缓存的群用户的资料信息,但不会触发 - (void)onUserInfoChanged: 回调。
如果群处于全体禁言状态,则禁言用户列表无效。
查询群的全体禁言状态
此状态定义在 NIMTeam
中,使用接口查询
- (BOOL)inAllMuteMode;
群禁言通知
通知的解析方式请参考之前小节 群组通知
。
单体禁言
单体禁言属于群内用户属性发生变更,SDK 单独定义了一个通知的操作类型 NIMTeamOperationTypeMute
。获得通知后判断通知 NIMTeamNotificationContent
的 operationType
是否为这个操作类型即可。
群全体禁言
群全体禁言属于群本身的属性发生变更, SDK 将这个变更定义在了群信息的更新通知里。取得 NIMTeamNotificationContent
的 attachment
字段,判断 NIMTeamUpdateTag
是否为 NIMTeamUpdateTagMuteMode
即可。
SDK 提供了群信息的拓展接口,开发者可以自行定义内容。
- (void)updateTeamCustomInfo:(NSString *)info
teamId:(NSString *)teamId
completion:(NIMTeamHandler)block
开发者可以通过 NIMTeam
的两个属性读取拓展信息:
应用方可以自行拓展这个字段做个性化配置,客户端不可以修改这个字段
@property (nonatomic,copy,readonly) NSString *serverCustomInfo;
应用方可以自行拓展这个字段做个性化配置,客户端可以修改这个字段
@property (nonatomic,copy,readonly) NSString *clientCustomInfo;
在集成聊天室之前,推荐开发者首先阅读这里。
聊天室功能对应的管理类为 NIMChatroomManager
。 NIMChatroomManager
提供了聊天室的业务管理,如进入/退出聊天室,获取相关信息以及权限操作等。目前不支持通过 SDK 接口建立/解散聊天室。
聊天室模型特点:
用户要在聊天室内说话,必须先调用接口进入此聊天室。用户进入聊天室后,不会收到此聊天室的历史消息推送。如有历史消息需求,可以调用消息查询接口进行显示。
- (void)enterChatroom:(NIMChatroomEnterRequest *)request
completion:(NIMChatroomEnterHandler)completion;
NIMChatroomEnterRequest
中包含了聊天室的基本数据信息,包括需要进入的聊天室 id 和一些供用户自定义的扩展字段,后续当前用户的所有聊天室消息都会带上登录时设置的扩展字段。
扩展包括:
roomExt
,这个字段可以放入用户在聊天室的自定义信息,如权限,头衔等等。这个扩展会放入每条消息的 messageExt
(需要转换成 NIMMessageChatroomExtension
) 字段的 roomExt
里。roomNotifyExt
,这个扩展会放入聊天室通知消息 content
(需要转换成 NIMChatroomNotificationContent
) 字段的 notifyExt
里。进入聊天室会建立新的连接,不同的聊天室对应着不同的连接,开发者可以监听连接状态做一些业务处理。
- (void)chatroom:(NSString *)roomId connectionStateChanged:(NIMChatroomConnectionState)state;
当进入聊天室后,再发生掉线问题时,SDK 将自动重连,无需开发者再次调用进入房间接口。
在重连时,可能遇到一些特殊网络错误(如聊天室用户被封禁,聊天室状态异常),会触发以下回调,开发者应该在这个回调中退出聊天室界面。
- (void)chatroom:(NSString *)roomId autoLoginFailed:(NSError *)error;
离开聊天室时,会断开聊天室对应的连接,并不再收到关于此聊天室的任何消息。
- (void)exitChatroom:(NSString *)roomId
completion:(NIMChatroomHandler)completion;
当用户被踢或者聊天室关闭时,会触发被踢回调,这个时候也会断开聊天室对应的连接:
- (void)chatroom:(NSString *)roomId beKicked:(NIMChatroomKickReason)reason;
聊天室消息收发接口与普通消息收发统一,在发送消息时指定会话类型为聊天室即可。会话 id 即为聊天室 id。
进入聊天室时,不会下发关于聊天室的历史消息,可以通过下面的接口查询聊天室消息历史。
- (void)fetchMessageHistory:(NSString *)roomId
option:(NIMHistoryMessageSearchOption *)option
result:(NIMFetchChatroomHistoryBlock)completion;
此接口可以远程获取聊天室信息,NIM SDK 不会缓存聊天室信息,开发者需要根据业务自己做好缓存。
- (void)fetchChatroomInfo:(NSString *)roomId
completion:(NIMChatroomInfoHandler)completion;
此接口可以修改聊天室信息,调用完这个接口后,开发者应该自己修改内存缓存的 NIMChatroom
对象。
此接口需要生成 NIMChatroomUpdateRequest
对象来完成请求。
NIMChatroomUpdateRequest
中的 needNotify
参数可以设置成功修改信息后云信服务器是否推送一条修改的聊天室消息通知。
NIMChatroomUpdateRequest
中的 notifyExt
参数可以设置推送的聊天室消息通知里带的自定义扩展字段。
- (void)updateChatroomInfo:(NIMChatroomUpdateRequest *)request
completion:(nullable NIMChatroomHandler)completion;
此接口可以远程获取聊天室成员列表,NIM SDK 不会缓存聊天室成员列表,开发者需要根据业务自己做好缓存。 NIM SDK 提供两种方式获取聊天室成员:
按锚点分页获取
- (void)fetchChatroomMembers:(NIMChatroomMemberRequest *)request
completion:(NIMChatroomMembersHandler)completion;
按用户 id 获取聊天室成员信息
- (void)fetchChatroomMembersByIds:(NIMChatroomMembersByIdsRequest *)request
completion:(NIMChatroomMembersHandler)completion;
此接口可以修改聊天室成员信息,调用完这个接口后,开发者应该自己修改内存缓存的 NIMChatroomMember
对象。
此接口需要生成 NIMChatroomMemberInfoUpdateRequest
对象来完成请求。
NIMChatroomMemberInfoUpdateRequest
中的 needNotify
参数可以设置成功修改信息后云信服务器是否推送一条修改的聊天室消息通知。
NIMChatroomMemberInfoUpdateRequest
中的 notifyExt
参数可以设置推送的聊天室消息通知里带的自定义扩展字段。
- (void)updateMyChatroomMemberInfo:(NIMChatroomMemberInfoUpdateRequest *)request
completion:(nullable NIMChatroomHandler)completion;
聊天室可以调整成员的类型,分固定成员和非固定成员两种,固定成员又分为创建者、管理员、普通成员和受限成员四种。禁言用户和拉黑用户都属于受限用户。
设置为管理员
- (void)markMemberManager:(NIMChatroomMemberUpdateRequest *)request
completion:(NIMChatroomHandler)completion;
设置为普通成员
- (void)markNormalMember:(NIMChatroomMemberUpdateRequest *)request
completion:(NIMChatroomHandler)completion;
设置为拉黑用户 拉黑的用户被移出黑名单后该成员变成非固定成员。
- (void)updateMemberBlack:(NIMChatroomMemberUpdateRequest *)request
completion:(NIMChatroomHandler)completion;
设置为禁言用户
- (void)updateMemberMute:(NIMChatroomMemberUpdateRequest *)request
completion:(NIMChatroomHandler)completion;
创建者或管理员可以将权限比自己低的用户踢出聊天室
- (void)kickMember:(NIMChatroomMemberKickRequest *)request
completion:(NIMChatroomHandler)completion;
在聊天室中所有的通知都以消息 NIMMessage
的形式展示,内部 messageObject
为 NIMNotificationTypeChatroom
类型的 NIMNotificationObject
。上层开发在收到具体消息需要进行过滤和显示。目前支持的聊天室消息事件定义在 NIMChatroomEventType
枚举里,具体有:
解析聊天室通知消息的详细步骤:
判断消息是否为通知消息
NIMMessage
的 messageType
字段是否为 NIMMessageTypeNotification
。判断通知消息是否为聊天室通知
NIMMessage
的 messageObject
字段强类型转换为 NIMNotificationObject
。NIMNotificationObject
中 notificationType
字段是否为 NIMNotificationTypeChatroom
。解析聊天室通知的具体内容
NIMNotificationObject
中 content
字段强类型转换为 NIMChatroomNotificationContent
。NIMChatroomNotificationContent
的具体字段。聊天室通知内容 NIMChatroomNotificationContent
的字段说明:
eventType
: 聊天室通知事件类型,表示具体属于哪一种聊天室通知,通知种类由 NIMChatroomEventType
枚举定义。source
: 通知的操作者,表示谁触发了这个通知,被封装为NIMChatroomNotificationMember
类型。targets
: 通知的被操作者,表示这个通知影响的用户,被封装为 NSArray
类型, NSArray
中每个元素被封装成 NIMChatroomNotificationMember
类型。notifyExt
: 通知的扩展字段,这个扩展字段是由每个触发通知的操作接口定义的。例如:
用户通过调用接口进入聊天室
- (void)enterChatroom:(NIMChatroomEnterRequest *)request completion:(nullable NIMChatroomEnterHandler)completion;
在这个请求中,请求对象 NIMChatroomEnterRequest
里可以定义一个通知扩展字段 roomNotifyExt
。 定义后当用户进入聊天室,会触发用户进入聊天室的事件消息通知,此时,收到消息的其他聊天室成员就可以通过读取 NIMChatroomNotificationContent
的 notifyExt
字段来获取进入的用户定义的 roomNotifyExt
字段。
ext
: 目前只有 NIMChatroomEventTypeAddMuteTemp
事件才有拓展信息,拓展信息为 NSNumber
,表示临时禁言时长。
聊天室允许管理员将部分成员禁言,或者全体禁言。禁言属于高级功能,需要调用云信服务器接口,客户端 SDK 仅提供聊天室禁言的通知功能。
聊天室禁言通知类型被同样定义在了 NIMChatroomEventType
中,分别为
具体解析步骤请参考之前小节 聊天室通知消息
。
除消息通道外,NIM SDK 还提供系统通知这种通道用于消息之外的通知分发。目前有两种类型:内置系统通知和自定义系统通知。
这是由 NIM SDK 预定义的通知类型,目前仅支持几种群操作的通知,如被邀请入群,SDK 负责这些通知的持久化。所有的内置系统通知都是通过
-(void)onReceiveSystemNotification:(NIMSystemNotification *)notification;
下发给 APP。为了保证整个程序逻辑的一致性,APP 需要针对不同类型的系统通知进行相应的操作。
内置系统通知的本地存储:(以下接口分为全量和过滤,过滤接口需要传入过滤器 NIMSystemNotificationFilter,可以按类型选择获取内置系统通知)
获取本地存储的内置系统通知
全量接口
- (NSArray *)fetchSystemNotifications:(NIMSystemNotification *)notification
limit:(NSInteger)limit;
过滤接口
- (NSArray *)fetchSystemNotifications:(NIMSystemNotification *)notification
limit:(NSInteger)limit
filter:(NIMSystemNotificationFilter *)filter;
获取本地存储的内置系统未读数
全量接口
- (NSInteger)allUnreadCount;
过滤接口
- (NSInteger)allUnreadCount:(NIMSystemNotificationFilter *)filter;
删除本地存储的内置系统通知
全量接口
- (void)deleteAllNotifications;
过滤接口
- (void)deleteAllNotifications:(NIMSystemNotificationFilter *)filter;
单条接口
- (void)deleteNotification:(NIMSystemNotification *)notification;
标记本地存储的内置系统通知为已读
全量接口
- (void)markAllNotificationsAsRead;
过滤接口
- (void)markAllNotificationsAsRead:(NIMSystemNotificationFilter *)filter;
单条接口
- (void)markNotificationsAsRead:(NIMSystemNotification *)notification;
除内置系统通知外,NIM SDK 也额外提供自定义系统给开发者,方便开发者进行业务逻辑的通知。这个通知既可以由客户端发起也可以由开发者服务器发起。
注意:自定义通知和自定义消息的不同之处在于,自定义消息归属于 NIM SDK 消息体系内,适用于会话,由 SDK 存储在消息数据库中,与 NIM SDK 其他内建消息类型一同展现给用户。而自定义通知主要用于第三方的一些事件状态通知,SDK 不存储,也不解析这些通知。SDK 仅仅负责替第三方传递和通知这些事件,起到透传的作用,收到自定义通知后的持久化工作需要由上层开发负责。
发送自定义通知(客户端)
- (void)sendCustomNotification:(NIMCustomSystemNotification *)notification
toSession:(NIMSession *)session
completion:(NIMSystemNotificationHandler)completion
客户端发起的自定义通知目前支持自定义如下字段:通知内容(推荐使用 json
组织),推送文案(如果没有则不进行 APNS 推送),是否只发给在线用户。最后一个字段的意义在于区分自定义通知的使用场景。选择只发给在线用户,当目标用户不在线时这条通知会被云信服务器丢弃,这种实现比较适合发送即时通知,如正在输入。反之云信服务器会缓存当前通知(有上限),并在目标用户上线后推送给目标用户。
接收自定义通知
- (void)onReceiveCustomSystemNotification:(NIMCustomSystemNotification *)notification;
云信允许用户订阅监听其他用户产生的事件,产生的事件的方式分为两种:
具体在线状态的业务逻辑可以参考 Demo 的 NTESSubscribeManager
实现。
- (void)publishEvent:(NIMSubscribeEvent *)event
completion:(NIMEventSubscribeBlock)completion;
在发布的前,需要自行构造出 NIMSubscribeEvent
对象,必须需要填写的字段为 type
, value
。 type
目前仅支持 “在线状态事件” , 即 NIMSubscribeSystemEventTypeOnline
。
- (void)subscribeEvent:(NIMSubscribeRequest *)request
completion:(NIMEventSubscribeResponseBlock)completion;
- (void)unSubscribeEvent:(NIMSubscribeRequest *)request
completion:(NIMEventSubscribeResponseBlock)completion;
在调用 订阅/取消订阅 事件接口前,需要先构造 NIMSubscribeRequest
订阅请求对象。
在订阅事件中,订阅请求中必需填写 type
,expiry
,publishers
字段。publishers
字段最多仅支持 100 个账号 id , 某些场景如在线状态,订阅人数会超过限制,需要多次调用此接口来满足业务,具体详见 Demo 中 NTESSubscribeManager
的 - (void)subscribeOnlineState
方法。
在取消订阅中,订阅请求中必须填写 type
字段,如果不填写 publishers
字段,则取消指定事件的全部订阅关系。
- (void)querySubscribeEvent:(NIMSubscribeRequest *)request
completion:(NIMEventSubscribeQueryBlock)completion;
SDK 提供查询本账号和指定账号存在的订阅关系接口,调用接口前,必须先构造 NIMSubscribeRequest
订阅请求对象。 其中,必须填写 type 字段 和 publishers 字段,查询人数最大支持 100 人。
目前不支持直接查询本账号和所有账号的订阅关系,上层需要维护好需要查询的用户 id, 通过多次调用此接口完成查询。
[[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
字段,控制是否需要发推送给手机端。
用户在发送消息的时候,设置 NIMMessage
的 apnsContent
属性进行消息推送内容设置。如果不设置 apnsContent
属性,将使用云信内置文案。设置 NIMMessage
的 apnsPayload
可以自定义推送参数。
示例代码:
NIMAudioObject *audioObject = [[NIMAudioObject alloc] initWithSourcePath:filePath];
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = audioObject;
message.apnsContent = @"发来了一段语音"; //对方收到的推送文案
用户在发送自定义系统通知的时候,设置 NIMCustomSystemNotification
的 apnsContent
属性来定制消息推送内容,同时可以设置 apnsPayload
来配置推送参数。
用户在发消息的时候,可以通过配置 NIMMessage
里的 apnsMemberOption
字段实现更为复杂的推送逻辑,目前这个字段只能在群会话中生效。
需要在给某些指定的成员推送特殊的文案
NIMMessageApnsMemberOption
的 userIds
字段,如果这个字段为nil,则表示推送给当前会话内的所有用户。NIMMessageApnsMemberOption
的 apnsContent
字段来指定特殊的推送文案,如果这个字段为 nil ,则使用消息本身的推送文案。强制推送。适用场景例如用户屏蔽了某个群,但是在群里有其他人 @ 了这个用户,则不管用户是否对这个群屏蔽推送,都要推送给这个用户如 “有人 @ 了你” 这样的文案。
NIMMessageApnsMemberOption
的 forcePush
字段为 YES
。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推送收不到问题排查方案
NIMUserManager
提供了用户帐号资料管理。以下几个接口仅当选择云信托管用户资料时有效,如果开发者不希望云信获取自己的用户数据,则需自行维护用户资料。
NIMUserManager
里,使用 NIMUser
对用户进行封装。其中用户信息为 NIMUserInfo
属性。 具体的信息字段由 NIMUserInfoUpdateTag
定义。 NIMUserInfoUpdateTag
内置了多个常用信息字段(有格式校验)和一个拓展字段 NIMUserInfoUpdateTagEx
供开发者自行拓展。
- (NIMUser *)userInfo:(NSString *)userId;
用户资料除自己之外,不保证其他用户资料实时更新。其他用户数据更新时机为:
调用 - (void)fetchUserInfos:completion:
方法刷新用户
收到此用户发来消息
程序再次启动,此时会同步好友资料
- (void)fetchUserInfos:(NSArray
completion:(NIMUserInfoBlock)completion
此接口可以批量从服务器获取用户资料,出于用户体验和流量成本考虑,不建议应用频繁调用此接口。对于用户数据实时性要求不高的页面,应尽量调用读取本地缓存接口。
- (void)updateMyUserInfo:(NSDictionary *)values completion:(NIMUserBlock)block;
只允许用户编辑自己的资料。此接口可以一次性编辑多个属性。如昵称,头像等,传入的数据键值对是 {@(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
提供了用户用户关系管理,以及对用户会话的消息设置。在云信中,不是好友也允许聊天。用户关系如果不托管给云信,开发者需要自己在应用服务器维护。
获取好友列表
- (NSArray *)myFriends;
好友列表有本地缓存,缓存会在手动/自动登录后与服务器自动进行同步更新。接口返回的是 NIMUser
列表。 NIMUser
封装了开发者向云信托管的好友ID,对此好友的会话设置(是否需要消息提醒,是否是拉黑用户等), 以及用户的详细信息 NIMUserInfo
(需要将用户信息交给云信托管)。
好友请求
- (void)requestFriend:(NIMUserRequest *)request
completion:(NIMUserBlock)block;
好友请求包括请求添加好友以及同意/拒绝好友请求两种。
好友请求需要构造出一个 NIMUserRequest
对象,封装添加对象用户的ID,以及添加方式。
代码示例:
NIMUserRequest *request = [[NIMUserRequest alloc] init];
request.userId = self.user.usrId; //封装用户ID
request.operation = NIMUserOperationRequest; //封装验证方式
request.message = @"跪求通过"; //封装自定义验证消息
验证方式有 NIMUserOperationAdd
和 NIMUserOperationRequest
两种。
第一种是不需要验证方式的,一旦请求后双方直接互为好友。
第二种是需要验证的,对方会收到一条类型为 NIMSystemNotificationTypeFriendAdd
系统通知 ( NIMSystemNotification
)。
验证回复有 同意 NIMUserOperationVerify
和 拒绝 NIMUserOperationReject
两种。 对方收到消息之后,可以选择接受或者拒绝好友邀请,此时同样调用 requestFriend:completion:
方法,传入拒绝对象的ID和验证回复类型即可。
好友添加成功后,会触发回调:
- (void)onFriendChanged:(NIMUser *)user;
删除好友
用户和用户之间可以解除好友关系。
- (void)deleteFriend:(NSString *)userId
completion:(NIMUserBlock)block;
解除成功后,会同时修改本地的缓存数据,并触发回调:
- (void)onFriendChanged:(NIMUser *)user;
云信中,黑名单和好友关系是互相独立的,即修改好友关系不会影响黑名单关系,同时,修改黑名单也不会对好友关系进行操作。
- (NSArray *)myBlackList;
黑名单列表有本地缓存,缓存会在手动/自动登录后与服务器自动进行同步更新。接口返回的是 NIMUser
列表。 NIMUser
封装了开发者向云信托管的好友ID,对此好友的会话设置(是否需要消息提醒,是否是拉黑用户等), 以及用户的详细信息 NIMUserInfo
(需要将用户信息交给云信托管)。
- (void)addToBlackList:(NSString *)userId
completion:(NIMUserBlock)block;
拉黑成功后,会同时修改本地缓存,并触发回调:
- (void)onBlackListChanged;
- (void)removeFromBlackBlackList:(NSString *)userId
completion:(NIMUserBlock)block;
移除成功后,会同时修改本地缓存,并触发回调:
- (void)onBlackListChanged;
- (BOOL)isUserInBlackList:(NSString *)userId;
此接口是根据本地缓存数据来判断是否拉黑的,在调用时请保证本地缓存是正确的(登录后有正常完成数据同步)。
云信中,可以单独设置是否开启某个用户的消息提醒,即对某个用户静音。静音关系和好友关系是互相独立的,修改好友关系不会影响静音关系,同时,修改静音关系也不会对好友关系进行操作。
- (NSArray *)myMuteUserList;
静音列表有本地缓存,缓存会在手动/自动登录后与服务器自动进行同步更新。接口返回的是 NIMUser
列表。 NIMUser
封装了开发者向云信托管的好友ID,对此好友的会话设置(是否需要消息提醒,是否是拉黑用户等), 以及用户的详细信息 NIMUserInfo
(需要将用户信息交给云信托管)。
- (void)updateNotifyState:(BOOL)notify
forUser:(NSString *)userId
completion:(NIMUserBlock)block;
设置成功之后,同时更新本地缓存数据。
- (BOOL)notifyForNewMsg:(NSString *)userId;
此接口是根据本地缓存数据来判断是否有消息提醒的,在调用时请保证本地缓存是正确的(登录后有正常完成数据同步)。
当修改用户资料成功后,会触发回调:
- (void)onUserInfoChanged:(NIMUser *)user;
智能对话机器人解决方案依托网易 IM 即时通讯、语音识别、语义理解等服务,为开发者提供人机交互API/SDK、语音识别、意图识别、知识库配置、动态接口等功能,可以在应用IM内快速集成场景丰富的智能对话机器人。
区别于开发者业务后台自行设定的机器人,网易波特中配置的机器人,类似网易精灵、小黄鸡这种通过配置知识库,与用户进行交流问答的智能对话机器人 。开发者可以在 网易波特服务 开通机器人服务。
机器人和云信账号是有绑定关系的,一个机器人账号对应了一个云信 id ,两者互相独立 , 云信内部负责维护对应关系。机器人所对应的云信用户不会在线,也不应该和其他正常用户有用户关系,如加好友,拉黑等。
智能对话机器人消息属于云信内置基础消息类型中的一种,发送示例请参考 发送消息 章节。
机器人内容格式规范可参考 机器人消息体模板说明 。
机器人的数据会在每次登录后自动同步至客户端。本地机器人数据由 NIMRobotManager 管理。
- (NSArray *)allRobots
- (BOOL)isValidRobot:(NSString *)userId
当机器人被移除时,userId 对应的机器人则为无效。
- (NIMRobot *)robotInfo:(NSString *)userId
机器人消息
机器人消息分上行消息和下行消息。用户向机器人发送的消息被称为上行消息,构造示例可以参考发送消息 章节;机器人向用户回复的消息被称为下行消息。
在 NIMRobotObject 里,判断是否上下行的字段为
@property (nonatomic, assign, readonly) BOOL isFromRobot;
同时,设置了只有机器人下行消息才有效的只读字段:
@property (nullable, nonatomic, copy, readonly) NSString *responseForMessageId
@property (nullable, nonatomic, copy, readonly) NSDictionary *response