新增 BannerScheduler 模块,统一管理 V2 Banner 的播放队列和状态,优化了 Banner 播放逻辑,支持优先级排序、状态控制和代理模式。更新 RoomAnimationView,集成 BannerScheduler,重构了 Banner 添加和播放逻辑,提升了代码可维护性和用户体验。同时,新增 BannerScheduler 的单元测试,确保功能的正确性和稳定性。

This commit is contained in:
edwinQQQ
2025-08-20 14:19:32 +08:00
parent aeb9fcd30e
commit be52c53b2f
6 changed files with 923 additions and 62 deletions

View File

@@ -33,6 +33,7 @@
#import "GiftComboManager.h"
#import "GiftAnimationManager.h"
#import "BannerScheduler.h"
#import "MSRoomGameWebVC.h"
#import "XPRoomViewController.h"
@@ -75,6 +76,8 @@
#import "XPRoomAnchorRankEnterView.h"
#import "MSRoomOnLineView.h"
#import "BannerScheduler.h"
static const CGFloat kTipViewStayDuration = 3.0;
static const CGFloat kTipViewMoveDuration = 0.5;
@@ -92,7 +95,8 @@ PIRoomGiftBroadcastWindowDelegate,
XPRoomAnchorRankBannerViewDelegate,
XPRoomGraffitiGiftAnimationViewDelegate,
UIGestureRecognizerDelegate
UIGestureRecognizerDelegate,
BannerSchedulerDelegate
>
@property (nonatomic, weak) id<RoomHostDelegate>hostDelegate;
@@ -134,6 +138,7 @@ UIGestureRecognizerDelegate
/// ---
@property (nonatomic, strong) NSMutableArray *roomBannertModelsQueueV2; // banner CP banner CP
@property (nonatomic, assign) BOOL isRoomBannerV2Displaying;
@property (nonatomic, strong) BannerScheduler *bannerScheduler; // Banner
// --- Brove
@property (nonatomic, strong) SVGAVideoEntity *broveSVGAEntity_lv_1;
@@ -267,6 +272,9 @@ UIGestureRecognizerDelegate
- (void)setupBanner {
_roomBannertModelsQueueV2 = [NSMutableArray array];
// Banner
self.bannerScheduler = [[BannerScheduler alloc] initWithDelegate:self];
}
@@ -510,8 +518,8 @@ UIGestureRecognizerDelegate
NSLog(@"🧪 DEBUG环境收到banner数据复制%ld份用于测试", (long)copyCount);
NSLog(@"🧪 原始banner类型: %@", NSStringFromClass([obj class]));
//
[self.roomBannertModelsQueueV2 addObject:obj];
//
[self.bannerScheduler enqueueBanner:obj];
//
for (int i = 1; i < copyCount; i++) {
@@ -532,68 +540,28 @@ UIGestureRecognizerDelegate
copiedObj.seq = obj.seq;
NSLog(@"🧪 复制第%d份banner数据", i + 1);
[self.roomBannertModelsQueueV2 addObject:copiedObj];
[self.bannerScheduler enqueueBanner:copiedObj];
}
NSLog(@"🧪 队列中banner总数: %ld", (long)self.roomBannertModelsQueueV2.count);
NSLog(@"🧪 队列中banner总数: %ld", (long)self.bannerScheduler.queueCount);
// banner
NSMutableDictionary *typeCount = [NSMutableDictionary dictionary];
for (AttachmentModel *banner in self.roomBannertModelsQueueV2) {
NSString *typeKey = [NSString stringWithFormat:@"%d", banner.second];
NSNumber *count = typeCount[typeKey];
typeCount[typeKey] = @(count.integerValue + 1);
}
NSLog(@"🧪 队列中banner类型分布:");
for (NSString *typeKey in typeCount.allKeys) {
NSLog(@" - 类型%@: %@个", typeKey, typeCount[typeKey]);
}
NSLog(@"🧪 队列状态: %@", [self.bannerScheduler queueStatusDescription]);
} else {
//
NSLog(@"🧪 DEBUG环境复制功能已禁用正常添加banner");
[self.roomBannertModelsQueueV2 addObject:obj];
[self.bannerScheduler enqueueBanner:obj];
}
#else
//
[self.roomBannertModelsQueueV2 addObject:obj];
[self.bannerScheduler enqueueBanner:obj];
#endif
if (!self.isRoomBannerV2Displaying) {
[self processNextRoomEffectAttachment];
}
}
- (void)sortBannerQueue {
RoomInfoModel *roomInfo = self.hostDelegate.getRoomInfo;
NSString *currentRoomUid = @(roomInfo.uid).stringValue;
NSString *currentUid = [AccountInfoStorage instance].getUid;
[self.roomBannertModelsQueueV2 sortUsingComparator:^NSComparisonResult(AttachmentModel * _Nonnull obj1, AttachmentModel * _Nonnull obj2) {
// obj1
NSArray *obj1UidList = [obj1.data valueForKey:@"uidList"];
NSNumber *obj1RoomUid = [obj1.data valueForKey:@"roomUid"];
BOOL obj1IsCurrentUser = obj1UidList && [obj1UidList containsObject:currentUid];
BOOL obj1IsCurrentRoom = obj1RoomUid && [obj1RoomUid.stringValue isEqualToString:currentRoomUid];
// obj2
NSArray *obj2UidList = [obj2.data valueForKey:@"uidList"];
NSNumber *obj2RoomUid = [obj2.data valueForKey:@"roomUid"];
BOOL obj2IsCurrentUser = obj2UidList && [obj2UidList containsObject:currentUid];
BOOL obj2IsCurrentRoom = obj2RoomUid && [obj2RoomUid.stringValue isEqualToString:currentRoomUid];
if (obj1IsCurrentUser && !obj2IsCurrentUser) {
return NSOrderedAscending;
} else if (!obj1IsCurrentUser && obj2IsCurrentUser) {
return NSOrderedDescending;
} else if (obj1IsCurrentRoom && !obj2IsCurrentRoom) {
return NSOrderedAscending;
} else if (!obj1IsCurrentRoom && obj2IsCurrentRoom) {
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}];
// FIFO
//
NSLog(@"🔄 RoomAnimationView: 使用先进先出策略,保持队列原有顺序");
}
- (void)processNextRoomEffectAttachment {
@@ -670,7 +638,7 @@ UIGestureRecognizerDelegate
- (void)playBroveBanner:(AttachmentModel *)obj {
if (!obj.data) {
self.isRoomBannerV2Displaying = NO;
[self processNextRoomEffectAttachment];
[self.bannerScheduler markBannerFinished];
return;
}
self.isRoomBannerV2Displaying = YES;
@@ -683,7 +651,7 @@ UIGestureRecognizerDelegate
@kStrongify(self);
NSLog(@"🔄 BravoGiftBannerView complete 回调被调用");
self.isRoomBannerV2Displaying = NO;
[self processNextRoomEffectAttachment];
[self.bannerScheduler markBannerFinished];
} exitCurrentRoom:^{
@kStrongify(self);
[self.hostDelegate exitRoom];
@@ -693,7 +661,7 @@ UIGestureRecognizerDelegate
- (void)playLuckyPackageBanner:(AttachmentModel *)obj {
if (!obj.data) {
self.isRoomBannerV2Displaying = NO;
[self processNextRoomEffectAttachment];
[self.bannerScheduler markBannerFinished];
return;
}
self.isRoomBannerV2Displaying = YES;
@@ -706,7 +674,7 @@ UIGestureRecognizerDelegate
@kStrongify(self);
NSLog(@"🔄 LuckyPackageBannerView complete 回调被调用");
self.isRoomBannerV2Displaying = NO;
[self processNextRoomEffectAttachment];
[self.bannerScheduler markBannerFinished];
} exitCurrentRoom:^{
@kStrongify(self);
[self.hostDelegate exitRoom];
@@ -720,7 +688,7 @@ UIGestureRecognizerDelegate
- (void)playRoomGiftBanner:(AttachmentModel *)obj {
if (!obj.data) {
self.isRoomBannerV2Displaying = NO;
[self processNextRoomEffectAttachment];
[self.bannerScheduler markBannerFinished];
return;
}
self.isRoomBannerV2Displaying = YES;
@@ -731,7 +699,7 @@ UIGestureRecognizerDelegate
@kStrongify(self);
NSLog(@"🔄 RoomHighValueGiftBannerAnimation complete 回调被调用");
self.isRoomBannerV2Displaying = NO;
[self processNextRoomEffectAttachment];
[self.bannerScheduler markBannerFinished];
}];
}
@@ -746,7 +714,7 @@ UIGestureRecognizerDelegate
complete:^{
@kStrongify(self);
self.isRoomBannerV2Displaying = NO;
[self processNextRoomEffectAttachment];
[self.bannerScheduler markBannerFinished];
}];
}
@@ -758,7 +726,7 @@ UIGestureRecognizerDelegate
@kStrongify(self);
NSLog(@"🔄 CPGiftBanner complete 回调被调用");
self.isRoomBannerV2Displaying = NO;
[self processNextRoomEffectAttachment];
[self.bannerScheduler markBannerFinished];
}];
}
@@ -769,7 +737,7 @@ UIGestureRecognizerDelegate
complete:^{
@kStrongify(self);
self.isRoomBannerV2Displaying = NO;
[self processNextRoomEffectAttachment];
[self.bannerScheduler markBannerFinished];
}];
}
@@ -932,7 +900,7 @@ UIGestureRecognizerDelegate
@kStrongify(self);
NSLog(@"🔄 LuckyGiftWinningBannerView complete 回调被调用");
self.isRoomBannerV2Displaying = NO;
[self processNextRoomEffectAttachment];
[self.bannerScheduler markBannerFinished];
} exitCurrentRoom:^{
@kStrongify(self);
[self.hostDelegate exitRoom];
@@ -971,7 +939,7 @@ UIGestureRecognizerDelegate
@kStrongify(self);
NSLog(@"🔄 GameUniversalBannerView complete 回调被调用");
self.isRoomBannerV2Displaying = NO;
[self processNextRoomEffectAttachment];
[self.bannerScheduler markBannerFinished];
} goToGame:^(NSInteger gameID) {
@kStrongify(self);
NSArray *baishunList = [self.hostDelegate getPlayList];
@@ -3510,6 +3478,111 @@ UIGestureRecognizerDelegate
self.savedTapPoint = CGPointZero;
}
- (void)debugBannerSchedulerStatus {
NSLog(@"🔍 BannerScheduler 调试信息:");
NSLog(@"%@", [self.bannerScheduler debugStatus]);
NSLog(@"🔍 RoomAnimationView 状态:");
NSLog(@" - isRoomBannerV2Displaying: %@", self.isRoomBannerV2Displaying ? @"YES" : @"NO");
NSLog(@" - bannerContainer.subviews.count: %ld", (long)self.bannerContainer.subviews.count);
}
- (void)testBannerScheduler {
NSLog(@"🧪 开始测试 BannerScheduler");
// Banner
AttachmentModel *testBanner = [[AttachmentModel alloc] init];
testBanner.second = Custom_Message_Sub_Super_Gift_Banner;
testBanner.data = @{@"test": @"data"};
[self.bannerScheduler enqueueBanner:testBanner];
NSLog(@"🧪 测试完成");
}
#pragma mark - BannerSchedulerDelegate
- (void)bannerScheduler:(BannerScheduler *)scheduler shouldPlayBanner:(id)banner {
NSLog(@"🎯 BannerSchedulerDelegate: 收到播放 Banner 请求");
NSLog(@"🎯 Banner 类型: %@", [banner class]);
// Banner AttachmentModel
if ([banner isKindOfClass:[AttachmentModel class]]) {
AttachmentModel *attachment = (AttachmentModel *)banner;
NSLog(@"🎯 AttachmentModel 类型: %ld", (long)attachment.second);
NSLog(@"🎯 AttachmentModel 数据: %@", attachment.data);
[self _playBannerWithAttachment:attachment];
} else {
NSLog(@"⚠️ BannerSchedulerDelegate: Banner 不是 AttachmentModel 类型");
}
}
- (void)bannerSchedulerDidFinishPlaying:(BannerScheduler *)scheduler {
// Banner
NSLog(@"🔄 BannerScheduler: Banner 播放完成");
}
- (void)bannerScheduler:(BannerScheduler *)scheduler didStartPlayingBanner:(id)banner {
// Banner
NSLog(@"🔄 BannerScheduler: Banner 开始播放 - 类型: %@", [banner class]);
}
#pragma mark - Private Methods
- (void)_playBannerWithAttachment:(AttachmentModel *)attachment {
NSLog(@"🎯 _playBannerWithAttachment: 开始处理 Banner - 类型: %ld", (long)attachment.second);
// bannerbanner
NSMutableArray *viewsToRemove = [NSMutableArray array];
for (UIView *subview in self.bannerContainer.subviews) {
[viewsToRemove addObject:subview];
NSLog(@"🔄 标记移除banner: %@", NSStringFromClass([subview class]));
}
for (UIView *view in viewsToRemove) {
[view removeFromSuperview];
}
// Banner
switch (attachment.second) {
case Custom_Message_Sub_General_Floating_Screen_One_Room:
case Custom_Message_Sub_General_Floating_Screen_All_Room:
NSLog(@"🎯 分发到 playGameBanner");
[self playGameBanner:attachment];
break;
case Custom_Message_Sub_Super_Gift_Winning_Coins_ALL_Room:
NSLog(@"🎯 分发到 playLuckyWinningBanner");
[self playLuckyWinningBanner:attachment];
break;
case Custom_Message_Sub_CP_Gift:
NSLog(@"🎯 分发到 playCPGiftBanner");
[self playCPGiftBanner:attachment];
break;
case Custom_Message_Sub_CP_Upgrade:
NSLog(@"🎯 分发到 playCPLevelUp");
[self playCPLevelUp:attachment];
break;
case Custom_Message_Sub_CP_Binding:
NSLog(@"🎯 分发到 playCPBinding");
[self playCPBinding:attachment];
break;
case Custom_Message_Sub_Gift_ChannelNotify:
NSLog(@"🎯 分发到 playRoomGiftBanner");
[self playRoomGiftBanner:attachment];
break;
case Custom_Message_Sub_LuckyPackage:
NSLog(@"🎯 分发到 playLuckyPackageBanner");
[self playLuckyPackageBanner:attachment];
break;
case Custom_Message_Sub_Super_Gift_Banner:
NSLog(@"🎯 分发到 playBroveBanner");
[self playBroveBanner:attachment];
break;
default:
NSLog(@"⚠️ 未知的 Banner 类型: %ld", (long)attachment.second);
//
[self.bannerScheduler markBannerFinished];
break;
}
}
@end