From 6d4061bea56a51d2e5e4dbe448e13d5f0d167e89 Mon Sep 17 00:00:00 2001 From: edwinQQQ Date: Tue, 19 Aug 2025 16:33:22 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=20AppDelegate+ThirdConfig=20?= =?UTF-8?q?=E4=B8=AD=20NIMSDK=20=E9=85=8D=E7=BD=AE=EF=BC=8C=E7=A1=AE?= =?UTF-8?q?=E4=BF=9D=E7=94=9F=E4=BA=A7=E7=8E=AF=E5=A2=83=E5=90=AF=E7=94=A8?= =?UTF-8?q?=20HTTPS=EF=BC=8C=E6=96=B0=E5=A2=9E=20CDN=20=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E5=9B=9E=E8=B0=83=E5=92=8C=E6=9C=80=E5=B0=8F=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E9=97=B4=E9=9A=94=E8=AE=BE=E7=BD=AE=EF=BC=8C=E6=8F=90=E5=8D=87?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=8F=AF=E7=BB=B4=E6=8A=A4=E6=80=A7=E5=92=8C?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=AE=8C=E6=95=B4=E6=80=A7=E3=80=82=E5=90=8C?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E9=87=8D=E6=9E=84=20GiftComboManager?= =?UTF-8?q?=EF=BC=8C=E6=96=B0=E5=A2=9E=E5=90=8E=E5=8F=B0=E5=A4=84=E7=90=86?= =?UTF-8?q?=E9=98=9F=E5=88=97=E5=92=8C=E7=BD=91=E7=BB=9C=E5=A4=84=E7=90=86?= =?UTF-8?q?=E9=98=9F=E5=88=97=EF=BC=8C=E4=BC=98=E5=8C=96=E5=AE=9A=E6=97=B6?= =?UTF-8?q?=E5=99=A8=E5=92=8C=E8=AF=B7=E6=B1=82=E5=A4=84=E7=90=86=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E7=A1=AE=E4=BF=9D=20UI=20=E5=9B=9E=E8=B0=83?= =?UTF-8?q?=E5=9C=A8=E4=B8=BB=E7=BA=BF=E7=A8=8B=E6=89=A7=E8=A1=8C=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=BC=BA=E7=94=A8=E6=88=B7=E4=BD=93=E9=AA=8C=E5=92=8C?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=8F=AF=E8=AF=BB=E6=80=A7=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- YuMi/Appdelegate/AppDelegate+ThirdConfig.m | 14 +- .../View/SendGiftView/GiftComboManager.m | 201 ++++++++++++------ 2 files changed, 144 insertions(+), 71 deletions(-) diff --git a/YuMi/Appdelegate/AppDelegate+ThirdConfig.m b/YuMi/Appdelegate/AppDelegate+ThirdConfig.m index 0298125a..8437e99a 100644 --- a/YuMi/Appdelegate/AppDelegate+ThirdConfig.m +++ b/YuMi/Appdelegate/AppDelegate+ThirdConfig.m @@ -115,12 +115,22 @@ UIKIT_EXTERN NSString * adImageName; // NIM SDK初始化 [NIMCustomObject registerCustomDecoder:[[CustomAttachmentDecoder alloc] init]]; + [[NIMSDKConfig sharedConfig] setShouldSyncStickTopSessionInfos:YES]; [NIMSDKConfig sharedConfig].shouldConsiderRevokedMessageUnreadCount = YES; - ///置顶会话同步 - [[NIMSDKConfig sharedConfig] setShouldSyncStickTopSessionInfos:YES]; + + // cdn统计回调不触发 + [NIMSDKConfig sharedConfig].cdnTrackInterval = 0; + + // 最小时间间隔设置为最小边界值 + [NIMSDKConfig sharedConfig].chatroomMessageReceiveMinInterval = 50; + #ifdef DEBUG [NIMSDKConfig sharedConfig].enabledHttpsForInfo = NO; [NIMSDKConfig sharedConfig].enabledHttpsForMessage = NO; +#else + // 生产环境启用HTTPS + [NIMSDKConfig sharedConfig].enabledHttpsForInfo = YES; + [NIMSDKConfig sharedConfig].enabledHttpsForMessage = YES; #endif } diff --git a/YuMi/Modules/YMRoom/View/SendGiftView/GiftComboManager.m b/YuMi/Modules/YMRoom/View/SendGiftView/GiftComboManager.m index 90545c79..a3e6c8ad 100644 --- a/YuMi/Modules/YMRoom/View/SendGiftView/GiftComboManager.m +++ b/YuMi/Modules/YMRoom/View/SendGiftView/GiftComboManager.m @@ -41,6 +41,10 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific // 定时器,处理请求的调度器 @property (nonatomic, strong) dispatch_source_t timer; +// 新增:后台处理队列 +@property (nonatomic, strong) dispatch_queue_t backgroundQueue; +@property (nonatomic, strong) dispatch_queue_t networkProcessingQueue; + @property (nonatomic, copy) NSArray *sendGiftToUIDs; @property (nonatomic, assign) GiftSourceType giftSourceType; @property (nonatomic, strong) GiftInfoModel *giftInfo; @@ -83,6 +87,11 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific sharedInstance.uiQueue = [NSMutableArray array]; sharedInstance.activeViews = [NSMutableArray array]; sharedInstance.requestQueue = [NSMutableArray array]; + + // 初始化后台处理队列 + sharedInstance.backgroundQueue = dispatch_queue_create("com.yumi.giftcombo.background", DISPATCH_QUEUE_CONCURRENT); + sharedInstance.networkProcessingQueue = dispatch_queue_create("com.yumi.giftcombo.network", DISPATCH_QUEUE_SERIAL); + [sharedInstance startProcessingUIQueue]; }); return sharedInstance; @@ -114,8 +123,8 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific // 开始连击,重置 - (void)reset { - NSLog(@"[Combo effect] 🔄 开始连击重置 - combo: %ld -> 1, enableCombo: %@, actionCallback: %@", - (long)self.combo, + NSLog(@"[Combo effect] 🔄 开始连击重置 - combo: %ld -> 1, enableCombo: %@, actionCallback: %@", + (long)self.combo, self.enableCombo ? @"YES" : @"NO", self.actionCallback ? @"可用" : @"为空"); @@ -129,10 +138,14 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific // 发送通知,让 GiftComboView 重置显示 [[NSNotificationCenter defaultCenter] postNotificationName:@"ComboCountReset" object:nil]; - // 检查是否应该显示连击面板 + // 检查是否应该显示连击面板 - 确保在主线程执行UI回调 if (self.actionCallback && self.enableCombo) { NSLog(@"[Combo effect] 📱 触发连击面板显示回调"); - self.actionCallback(ComboAction_ShowPanel); + @kWeakify(self); + [self safeExecuteUIBlock:^{ + @kStrongify(self); + self.actionCallback(ComboAction_ShowPanel); + }]; self.isCombing = YES; } else if (self.actionCallback && !self.enableCombo) { NSLog(@"[Combo effect] ⚠️ enableCombo为NO,不显示连击面板"); @@ -142,7 +155,11 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific if (self.handleRoomUIChanged) { NSLog(@"[Combo effect] 🎮 隐藏房间UI元素"); - self.handleRoomUIChanged(YES); + @kWeakify(self); + [self safeExecuteUIBlock:^{ + @kStrongify(self); + self.handleRoomUIChanged(YES); + }]; } NSLog(@"[Combo effect] ✅ 连击重置完成 - isCombing: %@", self.isCombing ? @"YES" : @"NO"); } @@ -186,10 +203,14 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific NSLog(@"[Combo effect] 🗑️ 清除连击状态"); [self forceBoomStateReset]; - // 通知UI移除连击面板 + // 通知UI移除连击面板 - 确保在主线程执行UI回调 if (self.actionCallback) { NSLog(@"[Combo effect] 📱 触发连击面板移除回调"); - self.actionCallback(ComboAction_RemovePanel); + @kWeakify(self); + [self safeExecuteUIBlock:^{ + @kStrongify(self); + self.actionCallback(ComboAction_RemovePanel); + }]; } } @@ -237,7 +258,7 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific [self clearAllQueues]; // 3. 重置所有状态标志 - NSLog(@"[Combo effect] 🔄 重置状态标志 - isCombing: %@ -> NO", + NSLog(@"[Combo effect] 🔄 重置状态标志 - isCombing: %@ -> NO", self.isCombing ? @"YES" : @"NO"); self.isCombing = NO; @@ -254,7 +275,7 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific // 5. 发送通知(优先级最高,通知所有相关组件) NSLog(@"[Combo effect] 📢 发送强制重置通知"); dispatch_async(dispatch_get_main_queue(), ^{ - [[NSNotificationCenter defaultCenter] postNotificationName:kBoomStateForceResetNotification + [[NSNotificationCenter defaultCenter] postNotificationName:kBoomStateForceResetNotification object:nil]; }); @@ -265,8 +286,8 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific self.handleRoomUIChanged(NO); }); } - NSLog(@"[Combo effect] ✅ 强制重置完成 - enableCombo保持: %@, actionCallback保持: %@", - self.enableCombo ? @"YES" : @"NO", + NSLog(@"[Combo effect] ✅ 强制重置完成 - enableCombo保持: %@, actionCallback保持: %@", + self.enableCombo ? @"YES" : @"NO", self.actionCallback ? @"可用" : @"为空"); } @@ -299,11 +320,11 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific // 新增:检查连击状态是否有效 - (BOOL)isComboStateValid { @synchronized (self) { - return self.isCombing && - self.enableCombo && - self.combo > 0 && - self.giftInfo != nil && - self.sendGiftToUIDs.count > 0; + return self.isCombing && + self.enableCombo && + self.combo > 0 && + self.giftInfo != nil && + self.sendGiftToUIDs.count > 0; } } @@ -373,12 +394,12 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific } dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); dispatch_source_set_timer(timer, - DISPATCH_TIME_NOW, - 0.2 * NSEC_PER_SEC, - 0.01 * NSEC_PER_SEC); + DISPATCH_TIME_NOW, + 0.2 * NSEC_PER_SEC, + 0.01 * NSEC_PER_SEC); @kWeakify(self); dispatch_source_set_event_handler(timer, ^{ @@ -407,7 +428,7 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific if (self.uiQueue.count == 0) { return; } - + GiftReceiveInfoModel *receiveInfo = [self.uiQueue firstObject]; NSLog(@"[Combo effect] 🎪 处理连击飘屏 - combo: %ld, giftId: %ld", (long)receiveInfo.comboCount, (long)receiveInfo.gift.giftId); [self.uiQueue xpSafeRemoveObjectAtIndex:0]; @@ -427,12 +448,12 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific // 如果更新了现有视图,就不需要创建新视图 return; } - + if (self.activeViews.count >= 2) { GiftComboFlagView *oldestView = [self.activeViews firstObject]; [self animateRemoveView:oldestView]; } - + CGFloat positionY = kGetScaleWidth(380); CGFloat positionX = isMSRTL() ? -self.containerView.bounds.size.width : self.containerView.bounds.size.width; GiftComboFlagView *flagView = [[GiftComboFlagView alloc] initWithFrame:CGRectMake(positionX, @@ -447,12 +468,12 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific [self animateRemoveView:flagView]; }]; [flagView updateReceiveInfoModel:receiveInfo animationType:0]; - + [self allCurrentFlagMoveDown]; - + [self.containerView addSubview:flagView]; [self.activeViews insertObject:flagView atIndex:0]; - + [self animateView:flagView positionY:positionY]; } @@ -473,10 +494,10 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific if (isMSRTL()) { // 获取屏幕宽度 CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; - + // 计算新的 x 坐标:屏幕宽度 - 视图宽度 - 右边距 CGFloat newX = screenWidth - 20 - kGetScaleWidth(300); - + // 更新 flagView 的 frame,使右边距离屏幕右边 20 像素 flagView.frame = CGRectMake(newX, positionY, kGetScaleWidth(300), 50); } else { @@ -493,7 +514,7 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific [self.activeViews removeObject:flagView]; flagView = nil; } - + [self allCurrentFlagMoveDown]; } @@ -510,7 +531,7 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific } index++; } - + return NO; } @@ -527,25 +548,25 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific if (self.timer) { return; // 如果定时器已经在运行,直接返回 } - - // 创建 GCD 定时器 - self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); - -//#if DEBUG -// dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC, 0.01 * NSEC_PER_SEC); -//#else - // 设置定时器时间间隔:每 0.25 秒执行一次 - dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, 0.25 * NSEC_PER_SEC, 0.01 * NSEC_PER_SEC); -//#endif - - // 定时器触发的事件处理 + // 创建 GCD 定时器 - 使用后台队列避免主线程阻塞 + self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.backgroundQueue); + + //#if DEBUG + // dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC, 0.01 * NSEC_PER_SEC); + //#else + // 优化:减少间隔提高响应速度,从0.25秒改为0.1秒 + dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC, 0.01 * NSEC_PER_SEC); + //#endif + + + // 定时器触发的事件处理 - 在后台队列执行 dispatch_source_set_event_handler(self.timer, ^{ [self processRequestQueue]; [self processGiftComboQueue]; }); - - // **立即执行一次处理方法** + + // **立即执行一次处理方法** [self processRequestQueue]; [self processGiftComboQueue]; @@ -559,7 +580,7 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific if (self.requestQueue.count == 0 && self.networkQueue.count == 0) { // 取消定时器 dispatch_source_cancel(self.timer); - + // 设置取消回调,在资源完全释放后将 timer 置为 nil @kWeakify(self); dispatch_source_set_cancel_handler(self.timer, ^{ @@ -572,15 +593,17 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific // 处理队列中的第一个请求 - (void)processGiftComboQueue { - @synchronized (self) { + @synchronized (self) { if (self.networkQueue.count > 0) { // 获取并移除队列中的第一个网络数据 id networkData = [self.networkQueue firstObject]; [self.networkQueue xpSafeRemoveObjectAtIndex:0]; - + // 处理逻辑 if ([networkData isKindOfClass:[AttachmentModel class]]) { - [self processGiftComboWith:(AttachmentModel *)networkData]; + dispatch_async(self.networkProcessingQueue, ^{ + [self processGiftComboWith:(AttachmentModel *)networkData]; + }); } else if ([networkData isKindOfClass:[NSDictionary class]]) { // 处理包含info和metadata的字典 NSDictionary *comboData = (NSDictionary *)networkData; @@ -610,7 +633,10 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific // 获取并移除队列中的第一个元数据 NSDictionary *dic = [self.requestQueue xpSafeObjectAtIndex:0]; if (dic) { - [self handleSendGift:dic]; + // 优化:在后台队列处理API请求,避免阻塞主线程 + dispatch_async(self.networkProcessingQueue, ^{ + [self handleSendGift:dic]; + }); [self.requestQueue removeObject:dic]; } } else { @@ -623,14 +649,14 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific // 统一配置方法,替代多个save方法 - (void)configureWithGiftInfo:(GiftInfoModel *)giftInfo - targetUIDs:(NSArray *)UIDs - roomUID:(NSString *)roomUID - sessionID:(NSString *)sessionID - userInfo:(UserInfoModel *)userInfo + targetUIDs:(NSArray *)UIDs + roomUID:(NSString *)roomUID + sessionID:(NSString *)sessionID + userInfo:(UserInfoModel *)userInfo countModel:(XPGiftCountModel *)countModel sourceType:(GiftSourceType)sourceType - sendType:(RoomSendGiftType)sendType - giftNum:(NSString *)giftNum { + sendType:(RoomSendGiftType)sendType + giftNum:(NSString *)giftNum { NSLog(@"[Combo effect] 🔧 统一配置连击参数"); @@ -644,7 +670,7 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific self.roomSendGiftType = sendType; self.giftNumPerTimes = giftNum; - NSLog(@"[Combo effect] ✅ 连击参数配置完成 - giftId: %ld, targetCount: %ld", + NSLog(@"[Combo effect] ✅ 连击参数配置完成 - giftId: %ld, targetCount: %ld", (long)giftInfo.giftId, (long)UIDs.count); } @@ -664,7 +690,7 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific } allUIDs = [allUIDs stringByAppendingString:item]; } - + NSDictionary *dic = @{ @"targetUids":allUIDs, @"giftNum":self.giftNumPerTimes, @@ -674,7 +700,7 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific @"giftType":[NSString stringWithFormat:@"%ld", self.roomSendGiftType], @"roomUid":self.roomUID }; - + NSLog(@"[Combo effect] 📦 添加礼物请求到队列 - giftId: %ld, targetUids: %@", (long)self.giftInfo.giftId, allUIDs); [self.requestQueue addObject:dic]; [self startProcessingQueue]; @@ -753,8 +779,13 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific } } + // 确保在主线程执行UI回调 if (self.actionCallback) { - self.actionCallback(ComboAction_Error); + @kWeakify(self); + [self safeExecuteUIBlock:^{ + @kStrongify(self); + self.actionCallback(ComboAction_Error); + }]; } } } @@ -781,9 +812,13 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific NSLog(@"[Combo effect] 🔢 API成功,递增连击计数 - 当前: %ld -> %ld", (long)self.combo, (long)(self.combo + 1)); self.combo += 1; - // 更新UI显示 + // 更新UI显示 - 确保在主线程执行UI回调 if (self.actionCallback) { - self.actionCallback(ComboAction_Combo_Count_Update); + @kWeakify(self); + [self safeExecuteUIBlock:^{ + @kStrongify(self); + self.actionCallback(ComboAction_Combo_Count_Update); + }]; } } @@ -809,8 +844,13 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific self.handleComboSuccess(receive, dic); } + // 确保在主线程执行UI回调 if (self.actionCallback) { - self.actionCallback(ComboAction_Update_After_Send_Success); + @kWeakify(self); + [self safeExecuteUIBlock:^{ + @kStrongify(self); + self.actionCallback(ComboAction_Update_After_Send_Success); + }]; } NSLog(@"[Combo effect] ✅ 连击礼物处理完成"); @@ -820,10 +860,12 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific NSLog(@"[Combo effect] 📨 发送云信自定义消息 - combo: %ld", (long)self.combo); NIMMessage *message = [[NIMMessage alloc]init]; + message.setting.quickDeliveryEnabled = YES; // 开启快速投递 + NIMCustomObject *object = [[NIMCustomObject alloc] init]; object.attachment = attachment; message.messageObject = object; - + UserInfoModel *userInfo = self.sendGiftUserInfo; XPMessageRemoteExtModel *extModel = [[XPMessageRemoteExtModel alloc] init]; extModel.androidBubbleUrl = userInfo.androidBubbleUrl; @@ -832,18 +874,39 @@ NSString * const kBoomStateForceResetNotification = @"BoomStateForceResetNotific extModel.platformRole = userInfo.platformRole; NSMutableDictionary *remoteExt = [NSMutableDictionary dictionaryWithObject:extModel.model2dictionary forKey:[NSString stringWithFormat:@"%ld", userInfo.uid]]; message.remoteExt = remoteExt; - + //构造会话 NIMSession *session = [NIMSession session:self.sessionID type:NIMSessionTypeChatroom]; - NSError *error = nil; - [[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error]; - if (error) { - NSLog(@"[Combo effect] ❌ 云信消息发送失败 - error: %@", error.localizedDescription); + // 优化:确保在主线程发送云信消息,因为云信SDK可能期望在主线程调用 + [self safeExecuteUIBlock:^{ + NSError *error = nil; + [[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error]; + if (error) { + NSLog(@"[Combo effect] ❌ 云信消息发送失败 - error: %@", error.localizedDescription); + } else { + NSLog(@"[Combo effect] ✅ 云信消息发送成功"); + } + }]; +} + +// 新增:辅助方法,统一处理UI回调的线程安全 +- (void)safeExecuteUIBlock:(void (^)(void))uiBlock { + if (!uiBlock) return; + + if ([NSThread isMainThread]) { + uiBlock(); } else { - NSLog(@"[Combo effect] ✅ 云信消息发送成功"); + dispatch_async(dispatch_get_main_queue(), uiBlock); } } +// 新增:性能监控方法 +- (void)logPerformanceMetrics { + NSLog(@"[Combo effect] 📊 性能指标 - 网络队列: %lu, 请求队列: %lu, 定时器: %@", + (unsigned long)self.networkQueue.count, + (unsigned long)self.requestQueue.count, + self.timer ? @"运行中" : @"已停止"); +} @end