优化 XPRoomViewController 中的视图初始化逻辑,移除 stageView 的添加,调整 messageContainerView 的约束。同时,修复 BravoGiftWinningFlagView 和 LuckyGiftWinningFlagView 的位置计算,确保视图在屏幕可见范围内,增强用户体验。新增智能销毁方法以优化 RoomAnimationView 的资源管理,确保重要动画播放时的清理逻辑更加安全。

This commit is contained in:
edwinQQQ
2025-08-29 15:55:02 +08:00
parent 0837457c9f
commit 8c024c0ec1
4 changed files with 177 additions and 60 deletions

View File

@@ -30,7 +30,7 @@
+ (BravoGiftWinningFlagViewModel *)display:(UIView *)superView with:(AttachmentModel *)attachment roomID:(NSInteger)roomID uID:(NSString *)UID {
BravoGiftWinningFlagViewModel *model = [BravoGiftWinningFlagViewModel modelWithJSON:attachment.data];
if (model.roomId != roomID || model.uid != UID.integerValue || model.tip == nil) {
if (model.roomId != roomID || model.uid != UID.integerValue || !model.tip) {
return model;
}
@@ -38,8 +38,27 @@
flagView.model = model;
flagView.alpha = 0;
flagView.frame = CGRectMake(0, 0, kGetScaleWidth(274), kGetScaleWidth(216));
flagView.center = CGPointMake(superView.center.x, kGetScaleWidth(216) + kGetScaleWidth(216)/2 - 40);
// 🔧
CGFloat viewWidth = kGetScaleWidth(274);
CGFloat viewHeight = kGetScaleWidth(216);
CGFloat screenWidth = KScreenWidth;
CGFloat screenHeight = KScreenHeight;
// Y 40%
CGFloat safeY = screenHeight * 0.4;
//
CGFloat maxY = screenHeight - viewHeight/2 - 20; // 20
CGFloat minY = viewHeight/2 + 20; // 20
CGFloat finalY = MAX(minY, MIN(safeY, maxY));
flagView.center = CGPointMake(screenWidth/2, finalY);
flagView.transform = CGAffineTransformMakeScale(0.1, 0.1);
NSLog(@"🎯 BravoGiftWinningFlagView: 位置计算 - screenSize: %.0fx%.0f, viewSize: %.0fx%.0f, center: (%.0f, %.0f)",
screenWidth, screenHeight, viewWidth, viewHeight, flagView.center.x, flagView.center.y);
[superView addSubview:flagView];
// 使alpha01

View File

@@ -54,8 +54,27 @@
winningFlagView.model = model;
winningFlagView.alpha = 0;
winningFlagView.frame = CGRectMake(0, 0, kGetScaleWidth(162), kGetScaleWidth(162));
winningFlagView.center = CGPointMake(superView.center.x, kGetScaleWidth(163) + kGetScaleWidth(162)/2);
// 🔧
CGFloat viewWidth = kGetScaleWidth(162);
CGFloat viewHeight = kGetScaleWidth(162);
CGFloat screenWidth = KScreenWidth;
CGFloat screenHeight = KScreenHeight;
// Y 35%
CGFloat safeY = screenHeight * 0.35;
//
CGFloat maxY = screenHeight - viewHeight/2 - 20; // 20
CGFloat minY = viewHeight/2 + 20; // 20
CGFloat finalY = MAX(minY, MIN(safeY, maxY));
winningFlagView.center = CGPointMake(screenWidth/2, finalY);
winningFlagView.transform = CGAffineTransformMakeScale(0.1, 0.1);
NSLog(@"🎯 LuckyGiftWinningFlagView: 位置计算 - screenSize: %.0fx%.0f, viewSize: %.0fx%.0f, center: (%.0f, %.0f)",
screenWidth, screenHeight, viewWidth, viewHeight, winningFlagView.center.x, winningFlagView.center.y);
[superView addSubview:winningFlagView];
// 使alpha01

View File

@@ -200,55 +200,29 @@ BannerSchedulerDelegate
- (void)removeItSelf {
NSLog(@"<22><> RoomAnimationView: 开始销毁");
// 🔧
[self cancelAllAnimations];
// 广
[[NIMSDK sharedSDK].broadcastManager removeDelegate:self];
//
[NSObject cancelPreviousPerformRequestsWithTarget:self];
// POP
[self pop_removeAllAnimations];
//
if (_giftEffectTimer && !dispatch_source_testcancel(_giftEffectTimer)) {
dispatch_source_cancel(_giftEffectTimer);
_giftEffectTimer = nil;
}
//
if (_giftEffectsQueue) {
self.giftEffectsQueue = NULL;
}
// <EFBFBD><EFBFBD> banner block
[self cleanupAllSubviews];
// 🔧 BannerScheduler
if (self.bannerScheduler) {
NSLog(@"<22><> 清理 BannerScheduler");
[self.bannerScheduler clearQueue];
[self.bannerScheduler pause];
self.bannerScheduler = nil;
}
//
[self cleanupGestureRecognizers];
//
[self cleanupCacheManagers];
//
[self removeNotificationObservers];
NSLog(@"<22><> RoomAnimationView: 销毁完成");
[self smartDestroy];
}
- (void)cancelAllAnimations {
NSLog(@" 取消所有动画");
NSLog(@"<EFBFBD><EFBFBD> 取消所有动画");
// <EFBFBD><EFBFBD>
BOOL hasImportantAnimation = [self hasImportantAnimationPlaying];
if (hasImportantAnimation) {
NSLog(@"⚠️ 检测到重要动画正在播放,延迟清理");
//
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self forceCancelAllAnimations];
});
return;
}
[self forceCancelAllAnimations];
}
- (void)forceCancelAllAnimations {
NSLog(@"🔄 强制取消所有动画");
// POP
[self pop_removeAllAnimations];
@@ -269,7 +243,25 @@ BannerSchedulerDelegate
}
- (void)cleanupAllSubviews {
NSLog(@" 清理所有子视图");
NSLog(@"🔄 清理所有子视图");
// <EFBFBD><EFBFBD>
BOOL hasImportantAnimation = [self hasImportantAnimationPlaying];
if (hasImportantAnimation) {
NSLog(@"⚠️ 检测到重要动画正在播放,延迟清理子视图");
//
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self forceCleanupAllSubviews];
});
return;
}
[self forceCleanupAllSubviews];
}
- (void)forceCleanupAllSubviews {
NSLog(@"<22><> 强制清理所有子视图");
//
NSArray *containers = @[self.bannerContainer, self.topContainer, self.middleContainer, self.bottomContainer];
@@ -280,7 +272,7 @@ BannerSchedulerDelegate
NSMutableArray *viewsToRemove = [NSMutableArray array];
for (UIView *subview in container.subviews) {
[viewsToRemove addObject:subview];
NSLog(@" 标记移除视图: %@ (从容器: %@)", NSStringFromClass([subview class]), NSStringFromClass([container class]));
NSLog(@"<EFBFBD><EFBFBD> 标记移除视图: %@ (从容器: %@)", NSStringFromClass([subview class]), NSStringFromClass([container class]));
}
for (UIView *view in viewsToRemove) {
@@ -289,7 +281,7 @@ BannerSchedulerDelegate
//
if (view.gestureRecognizers.count > 0) {
NSLog(@" 清理视图 %@ 上的 %lu 个手势识别器", NSStringFromClass([view class]), (unsigned long)view.gestureRecognizers.count);
NSLog(@"<EFBFBD><EFBFBD> 清理视图 %@ 上的 %lu 个手势识别器", NSStringFromClass([view class]), (unsigned long)view.gestureRecognizers.count);
for (UIGestureRecognizer *gesture in view.gestureRecognizers.copy) {
[view removeGestureRecognizer:gesture];
}
@@ -4031,4 +4023,91 @@ BannerSchedulerDelegate
}
}
// 🔧
- (BOOL)hasImportantAnimationPlaying {
// topContainer
for (UIView *subview in self.topContainer.subviews) {
if ([subview isKindOfClass:[BravoGiftWinningFlagView class]] ||
[subview isKindOfClass:[LuckyGiftWinningFlagView class]]) {
NSLog(@"🎯 检测到重要动画正在播放: %@", NSStringFromClass([subview class]));
return YES;
}
}
// middleContainer
for (UIView *subview in self.middleContainer.subviews) {
if ([subview isKindOfClass:[SVGAImageView class]] ||
[subview isKindOfClass:[VAPView class]] ||
[subview isKindOfClass:[PAGView class]]) {
NSLog(@"🎯 检测到礼物动画正在播放: %@", NSStringFromClass([subview class]));
return YES;
}
}
return NO;
}
// <EFBFBD><EFBFBD>
- (void)smartDestroy {
//
BOOL hasImportantAnimation = [self hasImportantAnimationPlaying];
if (hasImportantAnimation) {
NSLog(@"⚠️ 检测到重要动画正在播放,延迟销毁");
//
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self forceDestroy];
});
return;
}
[self forceDestroy];
}
- (void)forceDestroy {
NSLog(@"<22><> RoomAnimationView: 强制销毁");
// 广
[[NIMSDK sharedSDK].broadcastManager removeDelegate:self];
//
[NSObject cancelPreviousPerformRequestsWithTarget:self];
// POP
[self pop_removeAllAnimations];
//
if (_giftEffectTimer && !dispatch_source_testcancel(_giftEffectTimer)) {
dispatch_source_cancel(_giftEffectTimer);
_giftEffectTimer = nil;
}
//
if (_giftEffectsQueue) {
self.giftEffectsQueue = NULL;
}
// banner block
[self cleanupAllSubviews];
// BannerScheduler
if (self.bannerScheduler) {
NSLog(@"<22><> 清理 BannerScheduler");
[self.bannerScheduler clearQueue];
[self.bannerScheduler pause];
self.bannerScheduler = nil;
}
//
[self cleanupGestureRecognizers];
//
[self cleanupCacheManagers];
//
[self removeNotificationObservers];
NSLog(@"<22><> RoomAnimationView: 销毁完成");
}
@end

View File

@@ -604,7 +604,6 @@ XPCandyTreeInsufficientBalanceViewDelegate>
self.view.backgroundColor = [UIColor darkGrayColor];
[self.view addSubview:self.backContainerView];
[self.view addSubview:self.littleGameView];
[self.view addSubview:self.stageView];
[self.view addSubview:self.messageContainerView];
[self.view addSubview:self.quickMessageContainerView];
@@ -660,14 +659,8 @@ XPCandyTreeInsufficientBalanceViewDelegate>
make.height.mas_equalTo(kNavigationHeight);
}];
[self.stageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.trailing.mas_equalTo(self.view);
make.top.mas_equalTo(self.roomHeaderView.mas_bottom);
make.height.mas_equalTo(self.stageView.hightForStageView);
}];
[self.messageContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.stageView.mas_bottom);
make.top.equalTo(self.roomHeaderView.mas_bottom);
make.bottom.equalTo(self.quickMessageContainerView.mas_top).offset(-5);
make.leading.equalTo(self.view);
make.trailing.equalTo(self.sideMenu.mas_leading).offset(-10);
@@ -3195,9 +3188,16 @@ XPCandyTreeInsufficientBalanceViewDelegate>
}
- (StageView *)stageView {
// 🔧 StageViewManager stageView
if (self.stageViewManager && self.stageViewManager.currentStageView) {
return self.stageViewManager.currentStageView;
}
// 🔧 StageViewManager SocialStageView
if (!_stageView) {
_stageView = [[SocialStageView alloc] initWithDelegate:self];
_stageView.alpha = 0;
NSLog(@"⚠️ 使用降级 stageView: SocialStageView");
}
return _stageView;
}