NIMSessionInteractorImpl.m 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654
  1. //
  2. // NIMSessionInteraciton.m
  3. // NIMKit
  4. //
  5. // Created by chris on 2016/11/7.
  6. // Copyright © 2016年 NetEase. All rights reserved.
  7. //
  8. #import "NIMSessionInteractorImpl.h"
  9. #import <NIMSDK/NIMSDK.h>
  10. #import "NIMMessageModel.h"
  11. #import "NIMSessionTableAdapter.h"
  12. #import "NIMKitMediaFetcher.h"
  13. #import "NIMMessageMaker.h"
  14. #import "NIMLocationViewController.h"
  15. #import "NIMKitAudioCenter.h"
  16. #import "YOUPAILCIMTool.h"
  17. static const void * const NTESDispatchMessageDataPrepareSpecificKey = &NTESDispatchMessageDataPrepareSpecificKey;
  18. dispatch_queue_t NTESMessageDataPrepareQueue()
  19. {
  20. static dispatch_queue_t queue;
  21. static dispatch_once_t onceToken;
  22. dispatch_once(&onceToken, ^{
  23. queue = dispatch_queue_create("nim.demo.message.queue", 0);
  24. dispatch_queue_set_specific(queue, NTESDispatchMessageDataPrepareSpecificKey, (void *)NTESDispatchMessageDataPrepareSpecificKey, NULL);
  25. });
  26. return queue;
  27. }
  28. @interface NIMSessionInteractorImpl()<NIMLocationViewControllerDelegate,NIMMediaManagerDelegate>
  29. @property (nonatomic,strong) NIMSession *session;
  30. @property (nonatomic,strong) id<NIMSessionConfig> sessionConfig;
  31. @property (nonatomic,strong) NIMKitMediaFetcher *mediaFetcher;
  32. @property (nonatomic,strong) NSMutableArray *pendingChatroomModels;
  33. @property (nonatomic,strong) NSMutableArray *pendingAudioMessages;
  34. @end
  35. @implementation NIMSessionInteractorImpl
  36. - (instancetype)initWithSession:(NIMSession *)session
  37. config:(id<NIMSessionConfig>)sessionConfig
  38. {
  39. self = [super init];
  40. if (self) {
  41. _session = session;
  42. _sessionConfig = sessionConfig;
  43. [self addListener];
  44. }
  45. return self;
  46. }
  47. - (void)dealloc
  48. {
  49. [[NIMSDK sharedSDK].mediaManager stopPlay];
  50. [self removeListenner];
  51. }
  52. - (NSArray *)items
  53. {
  54. return [self.dataSource items];
  55. }
  56. - (void)markRead
  57. {
  58. if ([self shouldAutoMarkRead])
  59. {
  60. [[NIMSDK sharedSDK].conversationManager markAllMessagesReadInSession:self.session];
  61. if ([self shouldHandleReceipt])
  62. {
  63. [self sendMessageReceipt:self.items];
  64. }
  65. }
  66. }
  67. - (void)addMessages:(NSArray *)messages
  68. {
  69. NIMMessage *message = messages.firstObject;
  70. if (message.session.sessionType == NIMSessionTypeChatroom) {
  71. [self addChatroomMessages:messages];
  72. }else{
  73. [self addNormalMessages:messages];
  74. }
  75. }
  76. - (void)insertMessages:(NSArray *)messages
  77. {
  78. NSMutableArray *models = [[NSMutableArray alloc] init];
  79. for (NIMMessage *message in messages) {
  80. NIMMessageModel *model = [[NIMMessageModel alloc] initWithMessage:message];
  81. [models addObject:model];
  82. }
  83. NIMSessionMessageOperateResult *result = [self.dataSource insertMessageModels:models];
  84. [self.layout insert:result.indexpaths animated:YES];
  85. }
  86. - (void)addNormalMessages:(NSArray *)messages
  87. {
  88. NSMutableArray *models = [[NSMutableArray alloc] init];
  89. for (NIMMessage *message in messages) {
  90. if (message.isDeleted)
  91. {
  92. continue;
  93. }
  94. NIMMessageModel *model = [[NIMMessageModel alloc] initWithMessage:message];
  95. [models addObject:model];
  96. }
  97. NIMSessionMessageOperateResult *result = [self.dataSource addMessageModels:models];
  98. [self.layout insert:result.indexpaths animated:YES];
  99. }
  100. - (void)addChatroomMessages:(NSArray *)messages
  101. {
  102. if (!self.pendingChatroomModels) {
  103. self.pendingChatroomModels = [[NSMutableArray alloc] init];
  104. }
  105. __weak typeof(self) weakSelf = self;
  106. dispatch_async(NTESMessageDataPrepareQueue(), ^{
  107. NSMutableArray *models = [[NSMutableArray alloc] init];
  108. for (NIMMessage *message in messages)
  109. {
  110. if (message.isDeleted)
  111. {
  112. continue;
  113. }
  114. NIMMessageModel *model = [[NIMMessageModel alloc] initWithMessage:message];
  115. [weakSelf.layout calculateContent:model];
  116. [models addObject:model];
  117. }
  118. dispatch_async(dispatch_get_main_queue(), ^{
  119. [weakSelf.pendingChatroomModels addObjectsFromArray:models];
  120. [weakSelf processChatroomMessageModels];
  121. });
  122. });
  123. }
  124. - (NIMMessageModel *)deleteMessage:(NIMMessage *)message
  125. {
  126. NIMMessageModel *model = [self findMessageModel:message];
  127. if (model) {
  128. NIMSessionMessageOperateResult *result = [self.dataSource deleteMessageModel:model];
  129. [self.layout remove:result.indexpaths];
  130. }
  131. return model;
  132. }
  133. - (NIMMessageModel *)updateMessage:(NIMMessage *)message
  134. {
  135. NIMMessageModel *model = [self findMessageModel:message];
  136. if (model)
  137. {
  138. NIMSessionMessageOperateResult *result = [self.dataSource updateMessageModel:model];
  139. NSInteger index = [result.indexpaths.firstObject row];
  140. NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
  141. [self.layout update:indexPath];
  142. }
  143. return model;
  144. }
  145. - (NIMMessageModel *)findMessageModel:(NIMMessage *)message
  146. {
  147. if ([message isKindOfClass:[NIMMessage class]]) {
  148. return [self.dataSource findModel:message];
  149. }
  150. return nil;
  151. }
  152. - (NSInteger)findMessageIndex:(NIMMessage *)message {
  153. if ([message isKindOfClass:[NIMMessage class]]) {
  154. NIMMessageModel *model = [[NIMMessageModel alloc] initWithMessage:message];
  155. return [self.dataSource indexAtModelArray:model];
  156. }
  157. return -1;
  158. }
  159. - (void)checkReceipts:(NSArray<NIMMessageReceipt *> *)receipts
  160. {
  161. if ([self shouldHandleReceipt])
  162. {
  163. NSDictionary *models = [self.dataSource checkReceipts:receipts];
  164. for (NSNumber *index in models.allKeys) {
  165. NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index.integerValue inSection:0];
  166. [self.layout update:indexPath];
  167. }
  168. }
  169. }
  170. - (BOOL)shouldHandleReceipt
  171. {
  172. return [self.sessionConfig respondsToSelector:@selector(shouldHandleReceipt)] &&
  173. [self.sessionConfig shouldHandleReceipt];
  174. }
  175. - (void)markAllMessagesRead
  176. {
  177. [[NIMSDK sharedSDK].conversationManager markAllMessagesReadInSession:self.session];
  178. }
  179. - (void)sendMessageReceipt:(NSArray *)messages
  180. {
  181. [self.dataSource sendMessageReceipt:messages];
  182. }
  183. - (void)resetLayout
  184. {
  185. [self.layout resetLayout];
  186. }
  187. - (void)changeLayout:(CGFloat)inputHeight
  188. {
  189. [self.layout changeLayout:inputHeight];
  190. }
  191. - (void)cleanCache
  192. {
  193. [self.dataSource cleanCache];
  194. }
  195. - (void)loadMessages:(void (^)(NSArray *messages, NSError *error))handler
  196. {
  197. __weak typeof(self) wself = self;
  198. [self.dataSource loadHistoryMessagesWithComplete:^(NSInteger index, NSArray *messages, NSError *error) {
  199. if (messages.count) {
  200. [wself.layout layoutAfterRefresh];
  201. NSInteger firstRow = [self findMessageIndex:messages[0]] - 1;
  202. [wself.layout adjustOffset:firstRow];
  203. [wself.dataSource checkAttachmentState:messages];
  204. }
  205. if (handler) {
  206. handler(messages,error);
  207. }
  208. }];
  209. }
  210. - (void)pullUp {
  211. if (self.delegate && [self.delegate respondsToSelector:@selector(didPullUpMessageData)]) {
  212. [self.delegate didPullUpMessageData];
  213. }
  214. }
  215. - (void)pullUpMessages:(void(^)(NSArray *messages, NSError *error))handler {
  216. __weak typeof(self) wself = self;
  217. [self.dataSource loadNewMessagesWithComplete:^(NSInteger index, NSArray *messages, NSError *error) {
  218. if (messages.count) {
  219. [wself.layout layoutAfterRefresh];
  220. [wself.dataSource checkAttachmentState:messages];
  221. }
  222. if (handler) {
  223. handler(messages, error);
  224. }
  225. }];
  226. }
  227. - (void)resetMessages:(void (^)(NSError *error))handler
  228. {
  229. __weak typeof(self) weakSelf = self;
  230. [self.dataSource resetMessages:^(NSError *error) {
  231. if([weakSelf.delegate respondsToSelector:@selector(didFetchMessageData)])
  232. {
  233. [weakSelf.delegate didFetchMessageData];
  234. if (handler) {
  235. handler(error);
  236. }
  237. }
  238. }];
  239. }
  240. - (void)autoFetchMessages
  241. {
  242. if (![self.sessionConfig respondsToSelector:@selector(autoFetchWhenOpenSession)]
  243. || self.sessionConfig.autoFetchWhenOpenSession) {
  244. __weak typeof(self) weakSelf = self;
  245. [self.dataSource resetMessages:^(NSError *error) {
  246. if([weakSelf.delegate respondsToSelector:@selector(didFetchMessageData)])
  247. {
  248. [weakSelf.delegate didFetchMessageData];
  249. [weakSelf.dataSource checkAttachmentState:weakSelf.items];
  250. }
  251. }];
  252. }
  253. }
  254. - (void)setDataSource:(id<NIMSessionDataSource>)dataSource
  255. {
  256. _dataSource = dataSource;
  257. [self autoFetchMessages];
  258. }
  259. #pragma mark - 文本消息收发接口 modify by leo
  260. - (void)sendMessage:(NIMMessage *)message
  261. {
  262. WeakSelf;
  263. [YOUPAILCIMTool sendMessage:message sessionid:self.session.sessionId completion:^(NIMMessage *resultMsg,NSInteger filter,NSString *contentStr) {
  264. if (filter==0) {
  265. [[[NIMSDK sharedSDK] chatManager] sendMessage:resultMsg toSession:weakSelf.session error:nil];
  266. }else{
  267. resultMsg.text = contentStr;
  268. [[[NIMSDK sharedSDK] chatManager] sendMessage:resultMsg toSession:weakSelf.session error:nil];
  269. /*
  270. [[[NIMSDK sharedSDK] conversationManager] saveMessage:resultMsg forSession:weakSelf.session completion:^(NSError * _Nullable error) {
  271. }];
  272. */
  273. }
  274. }];
  275. }
  276. #pragma mark - Notifitcation
  277. - (void)vcBecomeActive:(NSNotification *)notification
  278. {
  279. NSArray *models = [self.dataSource items];
  280. [self sendMessageReceipt:models];
  281. }
  282. - (void)onUserInfoHasUpdatedNotification:(NSNotification *)notification {
  283. [self.delegate didRefreshMessageData];
  284. }
  285. - (void)onTeamMembersHasUpdatedNotification:(NSNotification *)notification {
  286. NSDictionary *userInfo = notification.userInfo;
  287. extern NSString *NIMKitInfoKey;
  288. NSArray *teamIds = userInfo[NIMKitInfoKey];
  289. if (self.session.sessionType == NIMSessionTypeTeam
  290. && ([teamIds containsObject:self.session.sessionId] || [teamIds containsObject:[NSNull null]])) {
  291. [self.delegate didRefreshMessageData];
  292. }
  293. }
  294. - (void)onTeamInfoHasUpdatedNotification:(NSNotification *)notification {
  295. NSDictionary *userInfo = notification.userInfo;
  296. extern NSString *NIMKitInfoKey;
  297. NSArray *teamIds = userInfo[NIMKitInfoKey];
  298. if (self.session.sessionType == NIMSessionTypeTeam
  299. && ([teamIds containsObject:self.session.sessionId] || [teamIds containsObject:[NSNull null]])) {
  300. [self.delegate didRefreshMessageData];
  301. }
  302. }
  303. #pragma mark - NIMSessionTableDataDelegate
  304. - (void)didRefreshMessageData
  305. {
  306. if ([self.delegate respondsToSelector:@selector(didRefreshMessageData)]) {
  307. [self.delegate didRefreshMessageData];
  308. }
  309. }
  310. #pragma mark - NIMMeidaButton
  311. - (void)mediaAudioPressed:(NIMMessageModel *)messageModel
  312. {
  313. if (![[NIMSDK sharedSDK].mediaManager isPlaying]) {
  314. [[NIMSDK sharedSDK].mediaManager switchAudioOutputDevice:NIMAudioOutputDeviceSpeaker];
  315. self.pendingAudioMessages = [self findRemainAudioMessages:messageModel.message];
  316. [[NIMKitAudioCenter instance] play:messageModel.message];
  317. } else {
  318. self.pendingAudioMessages = nil;
  319. [[NIMSDK sharedSDK].mediaManager stopPlay];
  320. }
  321. }
  322. #pragma mark 发送图片/小视频 //modify by leo 增加 content
  323. - (void)mediaPicturePressed
  324. {
  325. __weak typeof(self) weakSelf = self;
  326. [self.mediaFetcher fetchPhotoFromLibrary:^(NSArray *images, NSString *path, PHAssetMediaType type) {
  327. switch (type) {
  328. case PHAssetMediaTypeImage:
  329. {
  330. for (UIImage *image in images) {
  331. NIMMessage *message = [NIMMessageMaker msgWithImage:image];
  332. [YOUPAILCIMTool sendMessage:message sessionid:self.session.sessionId completion:^(NIMMessage *resultMsg,NSInteger filter,NSString *contentStr) {
  333. if (filter==0) {
  334. [[[NIMSDK sharedSDK] chatManager] sendMessage:resultMsg toSession:weakSelf.session error:nil];
  335. }else{
  336. [[[NIMSDK sharedSDK] conversationManager] saveMessage:resultMsg forSession:self.session completion:^(NSError * _Nullable error) {
  337. }];
  338. }
  339. }];
  340. }
  341. if (path) {
  342. NIMMessage *message;
  343. if ([path.pathExtension isEqualToString:@"HEIC"])
  344. {
  345. //iOS 11 苹果采用了新的图片格式 HEIC ,如果采用原图会导致其他设备的兼容问题,在上层做好格式的兼容转换,压成 jpeg
  346. UIImage *image = [UIImage imageWithContentsOfFile:path];
  347. message = [NIMMessageMaker msgWithImage:image];
  348. }
  349. else
  350. {
  351. message = [NIMMessageMaker msgWithImagePath:path];
  352. }
  353. [YOUPAILCIMTool sendMessage:message sessionid:self.session.sessionId completion:^(NIMMessage *resultMsg,NSInteger filter,NSString *contentStr) {
  354. if (filter==0) {
  355. [[[NIMSDK sharedSDK] chatManager] sendMessage:resultMsg toSession:weakSelf.session error:nil];
  356. }else{
  357. [[[NIMSDK sharedSDK] conversationManager] saveMessage:resultMsg forSession:self.session completion:^(NSError * _Nullable error) {
  358. }];
  359. }
  360. }];
  361. }
  362. }
  363. break;
  364. case PHAssetMediaTypeVideo:
  365. {
  366. NIMMessage *message = [NIMMessageMaker msgWithVideo:path];
  367. [YOUPAILCIMTool sendMessage:message sessionid:self.session.sessionId completion:^(NIMMessage *resultMsg,NSInteger filter,NSString *contentStr) {
  368. if (filter==0) {
  369. [[[NIMSDK sharedSDK] chatManager] sendMessage:resultMsg toSession:weakSelf.session error:nil];
  370. }else{
  371. [[[NIMSDK sharedSDK] conversationManager] saveMessage:resultMsg forSession:self.session completion:^(NSError * _Nullable error) {
  372. }];
  373. }
  374. }];
  375. }
  376. break;
  377. default:
  378. return;
  379. }
  380. }];
  381. }
  382. #pragma mark 发送快照 //modify by leo 增加 content
  383. - (void)mediaShootPressed
  384. {
  385. __weak typeof(self) weakSelf = self;
  386. [self.mediaFetcher fetchMediaFromCamera:^(NSString *path, UIImage *image) {
  387. NIMMessage *message;
  388. if (image) {
  389. message = [NIMMessageMaker msgWithImage:image];
  390. }else{
  391. message = [NIMMessageMaker msgWithVideo:path];
  392. }
  393. [YOUPAILCIMTool sendMessage:message sessionid:self.session.sessionId completion:^(NIMMessage *resultMsg,NSInteger filter,NSString *contentStr) {
  394. if (filter==0) {
  395. [[[NIMSDK sharedSDK] chatManager] sendMessage:resultMsg toSession:weakSelf.session error:nil];
  396. }else{
  397. if ([message.session isEqual:self.session]) {
  398. if ([self findMessageModel:message]) {
  399. [self updateMessage:message];
  400. }else{
  401. [self addMessages:@[message]];
  402. }
  403. }
  404. }
  405. }];
  406. }];
  407. }
  408. - (void)mediaLocationPressed
  409. {
  410. NIMLocationViewController *vc = [[NIMLocationViewController alloc] initWithNibName:nil bundle:nil];
  411. vc.delegate = self;
  412. UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
  413. [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:nav animated:YES completion:nil];
  414. }
  415. - (void)onSendLocation:(NIMKitLocationPoint *)locationPoint{
  416. NIMMessage *message = [NIMMessageMaker msgWithLocation:locationPoint];
  417. [[NIMSDK sharedSDK].chatManager sendMessage:message toSession:self.session error:nil];
  418. }
  419. - (void)onViewWillAppear
  420. {
  421. //fix bug: 竖屏进入会话界面,然后右上角进入群信息,再横屏,左上角返回,横屏的会话界面显示的就是竖屏时的大小
  422. [self cleanCache];
  423. dispatch_async(dispatch_get_main_queue(), ^{
  424. [self.layout reloadTable];
  425. });
  426. [[NIMSDK sharedSDK].mediaManager addDelegate:self];
  427. }
  428. - (void)onViewDidDisappear
  429. {
  430. [[NIMSDK sharedSDK].mediaManager removeDelegate:self];
  431. }
  432. #pragma mark - NIMSessionLayoutDelegate
  433. - (void)onRefresh
  434. {
  435. __weak typeof(self) wself = self;
  436. [self loadMessages:^(NSArray *messages, NSError *error) {
  437. [wself.layout layoutAfterRefresh];
  438. if (messages.count) {
  439. NSInteger row = [self findMessageIndex:messages[0]] - 1;
  440. [wself.layout adjustOffset:row];
  441. }
  442. if (messages.count)
  443. {
  444. [wself checkReceipts:nil];
  445. [wself markRead];
  446. }
  447. }];
  448. }
  449. #pragma mark - NIMMediaManagerDelegate
  450. - (void)playAudio:(NSString *)filePath didCompletedWithError:(nullable NSError *)error
  451. {
  452. if (!error)
  453. {
  454. BOOL disable = [self.sessionConfig respondsToSelector:@selector(disableAutoPlayAudio)] && [self.sessionConfig disableAutoPlayAudio];
  455. if (!disable)
  456. {
  457. [self playNextAudio];
  458. }
  459. }
  460. }
  461. - (void)playNextAudio
  462. {
  463. NIMMessage *message = self.pendingAudioMessages.lastObject;
  464. if (self.pendingAudioMessages.count) {
  465. [self.pendingAudioMessages removeLastObject];
  466. dispatch_async(dispatch_get_main_queue(), ^{
  467. [[NIMKitAudioCenter instance] play:message];
  468. });
  469. }
  470. }
  471. #pragma mark - Private
  472. //是否需要开启自动设置所有消息已读 : 某些场景不需要自动设置消息已读,如使用 3D touch 的场景预览会话界面内容
  473. - (BOOL)shouldAutoMarkRead
  474. {
  475. BOOL should = YES;
  476. if ([self.sessionConfig respondsToSelector:@selector(disableAutoMarkMessageRead)]) {
  477. should = ![self.sessionConfig disableAutoMarkMessageRead];
  478. }
  479. return should;
  480. }
  481. - (NIMKitMediaFetcher *)mediaFetcher
  482. {
  483. if (!_mediaFetcher) {
  484. _mediaFetcher = [[NIMKitMediaFetcher alloc] init];
  485. }
  486. return _mediaFetcher;
  487. }
  488. - (void)addListener
  489. {
  490. //声音的监听放在 viewWillApear 回调里,不在这里添加
  491. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(vcBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
  492. if (self.session.sessionType == NIMSessionTypeTeam) {
  493. extern NSString *const NIMKitTeamInfoHasUpdatedNotification;
  494. extern NSString *const NIMKitTeamMembersHasUpdatedNotification;
  495. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onTeamInfoHasUpdatedNotification:) name:NIMKitTeamInfoHasUpdatedNotification object:nil];
  496. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onTeamMembersHasUpdatedNotification:) name:NIMKitTeamMembersHasUpdatedNotification object:nil];
  497. }
  498. extern NSString *const NIMKitUserInfoHasUpdatedNotification;
  499. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onUserInfoHasUpdatedNotification:) name:NIMKitUserInfoHasUpdatedNotification object:nil];
  500. }
  501. - (void)removeListenner
  502. {
  503. //声音的监听放在 viewDidDisappear 回调里,不在这里移除
  504. [[NSNotificationCenter defaultCenter] removeObserver:self];
  505. }
  506. - (NSMutableArray *)findRemainAudioMessages:(NIMMessage *)message
  507. {
  508. if (message.isPlayed || [message.from isEqualToString:[NIMSDK sharedSDK].loginManager.currentAccount]) {
  509. //如果这条音频消息被播放过了 或者这条消息是属于自己的消息,则不进行轮播
  510. return nil;
  511. }
  512. NSMutableArray *messages = [[NSMutableArray alloc] init];
  513. [self.dataSource.items enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  514. if ([obj isKindOfClass:[NIMMessageModel class]]) {
  515. NIMMessageModel *model = (NIMMessageModel *)obj;
  516. BOOL isFromMe = [model.message.from isEqualToString:[[NIMSDK sharedSDK].loginManager currentAccount]];
  517. if ([model.message.messageId isEqualToString:message.messageId])
  518. {
  519. *stop = YES;
  520. }
  521. else if (model.message.messageType == NIMMessageTypeAudio && !isFromMe && !model.message.isPlayed)
  522. {
  523. [messages addObject:model.message];
  524. }
  525. }
  526. }];
  527. return messages;
  528. }
  529. - (void)processChatroomMessageModels
  530. {
  531. NSInteger pendingMessageCount = self.pendingChatroomModels.count;
  532. if (pendingMessageCount == 0) {
  533. return;
  534. }
  535. if ([self.layout canInsertChatroomMessages])
  536. {
  537. static NSInteger NTESMaxInsert = 2;
  538. NSArray *insert = nil;
  539. NSRange range;
  540. if (pendingMessageCount > NTESMaxInsert)
  541. {
  542. range = NSMakeRange(0, NTESMaxInsert);
  543. }
  544. else
  545. {
  546. range = NSMakeRange(0, pendingMessageCount);
  547. }
  548. insert = [self.pendingChatroomModels subarrayWithRange:range];
  549. [self.pendingChatroomModels removeObjectsInRange:range];
  550. NSUInteger leftPendingMessageCount = self.pendingChatroomModels.count;
  551. BOOL animated = leftPendingMessageCount== 0;
  552. NIMSessionMessageOperateResult *result = [self.dataSource addMessageModels:insert];
  553. [self.layout insert:result.indexpaths animated:animated];
  554. //聊天室消息最大保存消息量,超过这个消息量则把消息列表的前一半挪出内存。
  555. static NSInteger NTESMaxChatroomMessageCount = 200;
  556. NSInteger count = self.dataSource.items.count;
  557. if (count > NTESMaxChatroomMessageCount) {
  558. NSRange deleteRange = NSMakeRange(0, count/2);
  559. NSArray *delete = [self.dataSource deleteModels:deleteRange];
  560. [self.layout remove:delete];
  561. }
  562. [self processChatroomMessageModels];
  563. }
  564. else
  565. {
  566. //不能插入是为了保证界面流畅,比如滑动,此时暂停处理
  567. __weak typeof(self) weakSelf = self;
  568. NSTimeInterval delay = 1;
  569. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  570. [weakSelf processChatroomMessageModels];
  571. });
  572. }
  573. }
  574. @end