在 XPHomePartyViewController、XPNewHomePartyCollectionViewCell 和 XPPartyRoomItemCollectionViewCell 中新增 prepareForReuse 方法以优化内存管理,确保在复用时清理资源。更新 XPRoomViewController 以实现房间UID的CP拉取逻辑,并在 dealloc 方法中添加资源释放保障。优化 MicMidpointRectManager 中的安全级别计算逻辑,确保代码整洁性。
This commit is contained in:
@@ -190,6 +190,45 @@
|
||||
make.height.mas_equalTo(kGetScaleWidth(20));
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)prepareForReuse {
|
||||
[super prepareForReuse];
|
||||
// 停止并清理动画,避免复用时占用内存
|
||||
[self.pkImageView stopAnimation];
|
||||
self.pkImageView.videoItem = nil;
|
||||
self.pkImageView.hidden = YES;
|
||||
|
||||
// 重置图像资源,打断潜在的异步加载引用
|
||||
[self.avatarView cancelLoadImage];
|
||||
self.avatarView.imageUrl = nil;
|
||||
self.rankImageView.image = nil;
|
||||
[self.tagImageView cancelLoadImage];
|
||||
self.tagImageView.image = nil;
|
||||
self.tagImageView.hidden = YES;
|
||||
[self.levelImageView cancelLoadImage];
|
||||
self.levelImageView.imageUrl = nil;
|
||||
[self.boomImageView cancelLoadImage];
|
||||
self.boomImageView.imageUrl = nil;
|
||||
|
||||
// 重置文本
|
||||
self.nameLabel.attributedText = nil;
|
||||
self.nameLabel.text = @"";
|
||||
self.subLabel.text = @"";
|
||||
self.heatNumLable.text = @"0";
|
||||
|
||||
// 重置成员头像视图:取消下载+清空,隐藏
|
||||
for (NetImageView *iconView in self.iconViews) {
|
||||
[iconView cancelLoadImage];
|
||||
iconView.imageUrl = nil;
|
||||
iconView.hidden = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
// 组件销毁时也保证动画资源释放
|
||||
[self.pkImageView stopAnimation];
|
||||
self.pkImageView.videoItem = nil;
|
||||
}
|
||||
- (void)setRoomInfo:(HomePlayRoomModel *)roomInfo{
|
||||
|
||||
_roomInfo = roomInfo;
|
||||
|
@@ -123,6 +123,28 @@
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)prepareForReuse {
|
||||
[super prepareForReuse];
|
||||
// 重置图像,释放引用,避免复用持有
|
||||
[self.avatarView cancelLoadImage];
|
||||
self.avatarView.imageUrl = nil;
|
||||
self.rankImageView.image = nil;
|
||||
[self.tagImageView cancelLoadImage];
|
||||
self.tagImageView.image = nil;
|
||||
[self.levelImageView cancelLoadImage];
|
||||
self.levelImageView.imageUrl = nil;
|
||||
[self.boomImageView cancelLoadImage];
|
||||
self.boomImageView.imageUrl = nil;
|
||||
[self.flagImage cancelLoadImage];
|
||||
self.flagImage.imageUrl = nil;
|
||||
|
||||
// 重置文本
|
||||
self.nameLabel.attributedText = nil;
|
||||
self.nameLabel.text = @"";
|
||||
self.subLabel.text = @"";
|
||||
self.heatNumLable.text = @"0";
|
||||
}
|
||||
|
||||
- (void)setRoomInfo:(HomePlayRoomModel *)roomInfo {
|
||||
_roomInfo = roomInfo;
|
||||
self.avatarView.imageUrl = roomInfo.avatar;
|
||||
|
@@ -91,6 +91,25 @@ static NSString * const kHomeLayoutTypeKey = @"kHomeLayoutTypeKey";
|
||||
return _bannerView;
|
||||
}
|
||||
|
||||
- (void)prepareForReuse {
|
||||
[super prepareForReuse];
|
||||
// 安全释放:停止轮播并清理数据,避免离屏仍占用内存/CPU
|
||||
self.bannerView.autoScroll = NO;
|
||||
self.bannerView.imageURLStringsGroup = nil;
|
||||
}
|
||||
|
||||
- (void)stopAndRelease {
|
||||
// 离屏时显式停止以释放资源
|
||||
self.bannerView.autoScroll = NO;
|
||||
}
|
||||
|
||||
// 进入可见区域后恢复滚动(由 VC 调用)
|
||||
- (void)resumeIfNeeded {
|
||||
if (self.bannerView.imageURLStringsGroup.count > 0) {
|
||||
self.bannerView.autoScroll = YES;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - SDCycleScrollViewDelegate
|
||||
- (void)cycleScrollView:(SDCycleScrollView *)cycleScrollView didSelectItemAtIndex:(NSInteger)index {
|
||||
HomeBannerInfoModel * bannerInfo = [self.bannerInfoList xpSafeObjectAtIndex:index];
|
||||
@@ -152,8 +171,16 @@ static NSString * const kHomeLayoutTypeKey = @"kHomeLayoutTypeKey";
|
||||
}
|
||||
|
||||
- (void)loadLayoutTypeFromCache {
|
||||
// 从 UserDefaults 读取缓存的布局类型,默认为一列布局(NO)
|
||||
self.isTwoColumnLayout = [[NSUserDefaults standardUserDefaults] boolForKey:kHomeLayoutTypeKey];
|
||||
// 从 UserDefaults 读取缓存的布局类型;若无记录,则默认两列以降低进入内存消耗
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
id storedValue = [defaults objectForKey:kHomeLayoutTypeKey];
|
||||
if (storedValue == nil) {
|
||||
self.isTwoColumnLayout = YES; // 默认两列
|
||||
[defaults setBool:YES forKey:kHomeLayoutTypeKey];
|
||||
[defaults synchronize];
|
||||
} else {
|
||||
self.isTwoColumnLayout = [storedValue boolValue];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)saveLayoutTypeToCache {
|
||||
@@ -387,6 +414,27 @@ static NSString * const kHomeLayoutTypeKey = @"kHomeLayoutTypeKey";
|
||||
return CGSizeMake(kGetScaleWidth(345), kGetScaleWidth(92));
|
||||
}
|
||||
|
||||
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
// 离屏安全释放:对不同类型 cell 做最小必要释放
|
||||
if ([cell isKindOfClass:[HomePartyBannerCell class]]) {
|
||||
HomePartyBannerCell *bannerCell = (HomePartyBannerCell *)cell;
|
||||
[bannerCell stopAndRelease];
|
||||
} else if ([cell isKindOfClass:[XPNewHomePartyCollectionViewCell class]]) {
|
||||
// 触发其内部 prepareForReuse 等价释放
|
||||
[cell prepareForReuse];
|
||||
} else if ([cell isKindOfClass:[XPPartyRoomItemCollectionViewCell class]]) {
|
||||
[cell prepareForReuse];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
// 进入可见区:如为 banner,恢复自动滚动(若有数据)
|
||||
if ([cell isKindOfClass:[HomePartyBannerCell class]]) {
|
||||
HomePartyBannerCell *bannerCell = (HomePartyBannerCell *)cell;
|
||||
[bannerCell resumeIfNeeded];
|
||||
}
|
||||
}
|
||||
|
||||
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
|
||||
id item = [self.datasource xpSafeObjectAtIndex:indexPath.row];
|
||||
|
||||
|
@@ -107,7 +107,7 @@
|
||||
}
|
||||
BOOL match = (obj.uid == leftUid && obj.loverUid == rightUid) || (obj.uid == rightUid && obj.loverUid == leftUid);
|
||||
if (match) {
|
||||
NSInteger safeLevel = MAX(1, MIN(5, obj.cpLevel+1));
|
||||
NSInteger safeLevel = MAX(1, MIN(5, obj.cpLevel));
|
||||
NSString *svgaName = [NSString stringWithFormat:@"mic_cp_lv%ld", (long)safeLevel];
|
||||
[self playSVGAAnimationAtFrame:frame withNamed:svgaName];
|
||||
break;
|
||||
|
@@ -221,6 +221,8 @@ XPCandyTreeInsufficientBalanceViewDelegate>
|
||||
@property (nonatomic, assign) BOOL currentUserWasOnMic; // 当前用户之前是否在麦上
|
||||
@property (nonatomic, assign) NSInteger currentUserMicPosition; // 当前用户的麦位位置(-1表示不在麦上)
|
||||
@property (nonatomic, assign) BOOL hasCompletedRoomInitialization; // 是否已完成进房初始化
|
||||
/// 是否已请求按房间UID获取CP列表(首进房)
|
||||
@property (nonatomic, assign) BOOL hasRequestedInitialCpByRoomUid;
|
||||
|
||||
@end
|
||||
|
||||
@@ -363,6 +365,65 @@ XPCandyTreeInsufficientBalanceViewDelegate>
|
||||
self.upMicAskTimer = nil;
|
||||
}
|
||||
|
||||
// 🔧 释放保障:解散可能残留的弹窗/蒙层
|
||||
[TTPopup dismiss];
|
||||
|
||||
// 🔧 释放保障:停止 Turbo Mode Tips 监听(若支持)
|
||||
if ([[XPTurboModeTipsManager sharedManager] respondsToSelector:@selector(stopTipsMonitoringInRoom)]) {
|
||||
[[XPTurboModeTipsManager sharedManager] performSelector:@selector(stopTipsMonitoringInRoom)];
|
||||
}
|
||||
|
||||
// 🔧 释放保障:清空 GiftComboManager 的 UI 回调,避免对 VC 的强引用
|
||||
if ([GiftComboManager sharedManager]) {
|
||||
[[GiftComboManager sharedManager] setHandleRoomUIChanged:nil];
|
||||
}
|
||||
|
||||
// 🔧 释放保障:清空 sideMenu 的 block 回调
|
||||
if (self.sideMenu) {
|
||||
if ([self.sideMenu respondsToSelector:@selector(setOpenRedPacketHandle:)]) {
|
||||
[self.sideMenu performSelector:@selector(setOpenRedPacketHandle:) withObject:nil];
|
||||
}
|
||||
if ([self.sideMenu respondsToSelector:@selector(setShowSendGiftView:)]) {
|
||||
[self.sideMenu performSelector:@selector(setShowSendGiftView:) withObject:nil];
|
||||
}
|
||||
}
|
||||
|
||||
// 🔧 释放保障:置空各子视图/滚动视图的 delegate,规避潜在强引用
|
||||
NSArray *possibleDelegates = @[
|
||||
self.backContainerView,
|
||||
self.stageView,
|
||||
self.messageContainerView,
|
||||
self.quickMessageContainerView,
|
||||
self.menuContainerView,
|
||||
self.functionView,
|
||||
self.littleGameView,
|
||||
self.anchorScrollView
|
||||
];
|
||||
for (id obj in possibleDelegates) {
|
||||
if (!obj) { continue; }
|
||||
if ([obj respondsToSelector:@selector(setDelegate:)]) {
|
||||
[obj performSelector:@selector(setDelegate:) withObject:nil];
|
||||
}
|
||||
if ([obj respondsToSelector:@selector(setHostDelegate:)]) {
|
||||
[obj performSelector:@selector(setHostDelegate:) withObject:nil];
|
||||
}
|
||||
if ([obj respondsToSelector:@selector(setAnchorScrollDelegate:)]) {
|
||||
[obj performSelector:@selector(setAnchorScrollDelegate:) withObject:nil];
|
||||
}
|
||||
}
|
||||
|
||||
// 🔧 释放保障:移除视图层级,断开 UI 链接
|
||||
[self __removeAllViews];
|
||||
self.anchorScrollView = nil;
|
||||
self.backContainerView = nil;
|
||||
self.stageView = nil;
|
||||
self.messageContainerView = nil;
|
||||
self.quickMessageContainerView = nil;
|
||||
self.menuContainerView = nil;
|
||||
self.sideMenu = nil;
|
||||
self.functionView = nil;
|
||||
self.littleGameView = nil;
|
||||
|
||||
NSLog(@"🔄 XPRoomViewController: 销毁完成");
|
||||
}
|
||||
|
||||
@@ -1874,6 +1935,9 @@ XPCandyTreeInsufficientBalanceViewDelegate>
|
||||
|
||||
// 🔧 新增:初始化当前用户的麦位状态
|
||||
[self initializeCurrentUserMicStatus];
|
||||
|
||||
// 🔧 首次进房:尝试在初始化就绪后触发按房间UID的CP拉取(幂等)
|
||||
[self tryRequestInitialCpByRoomUidIfNeeded];
|
||||
|
||||
//上报进房
|
||||
if (self.roomInfo != nil) {
|
||||
@@ -1887,6 +1951,18 @@ XPCandyTreeInsufficientBalanceViewDelegate>
|
||||
}
|
||||
}
|
||||
|
||||
/// 幂等触发:按房间UID拉取全量CP,仅在初始化完成后触发一次
|
||||
- (void)tryRequestInitialCpByRoomUidIfNeeded {
|
||||
@synchronized (self) {
|
||||
if (self.hasRequestedInitialCpByRoomUid) { return; }
|
||||
if (!self.hasCompletedRoomInitialization) { return; }
|
||||
if (self.isExitingRoom || !self.isViewActive) { return; }
|
||||
self.hasRequestedInitialCpByRoomUid = YES;
|
||||
}
|
||||
NSString *roomUid = [NSString stringWithFormat:@"%ld", (long)self.roomInfo.uid];
|
||||
[self.presenter micCpListByRoomUid:roomUid];
|
||||
}
|
||||
|
||||
- (void)enterRoomFail:(NSInteger)code {
|
||||
[XNDJTDDLoadingTool hideHUDInView:self.navigationController.view];
|
||||
[self hideHUD];
|
||||
@@ -4221,6 +4297,8 @@ XPCandyTreeInsufficientBalanceViewDelegate>
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
self.hasCompletedRoomInitialization = YES;
|
||||
NSLog(@"🔧 进房初始化完成,后续麦位变动将触发 micCpListByUidList 调用");
|
||||
// 初始化完成后,幂等尝试按房间UID拉取一次全量CP
|
||||
[self tryRequestInitialCpByRoomUidIfNeeded];
|
||||
});
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user