- fixes some UI memory leaks

- clear some obsolete codes
This commit is contained in:
TrueZhuanjia committed 2025-11-07 23:21:53 +08:00
1 parent 5750b99af3
commit 700552bd75
5 files changed
+49 -115

No files matched your search

-1
View File
@@ -425,7 +425,6 @@ static const float REFRESH_CYCLE = 2.0f;
[self.transparentButton.bottomAnchor constraintEqualToAnchor:self.separatorLine.topAnchor], [self.transparentButton.bottomAnchor constraintEqualToAnchor:self.separatorLine.topAnchor],
]]; ]];
_widthConstraint.constant = _cardContentpadding*2 + appButtonWidth + 15*_sizeFactor + launchButtonWidth; _widthConstraint.constant = _cardContentpadding*2 + appButtonWidth + 15*_sizeFactor + launchButtonWidth;
_heightConstraint.constant = _cardContentpadding*2 + _iconBackgroundView.frame.size.height + iconAndButtonSpacing + buttonHeight + 1; _heightConstraint.constant = _cardContentpadding*2 + _iconBackgroundView.frame.size.height + iconAndButtonSpacing + buttonHeight + 1;
@@ -56,11 +56,13 @@ static const CGFloat cellOffsetY = 20;
if (!self.cardView) { if (!self.cardView) {
self.cardView = [[HostCardView alloc] initWithHost:host andSizeFactor:[self getHostCardSizeFactor]]; self.cardView = [[HostCardView alloc] initWithHost:host andSizeFactor:[self getHostCardSizeFactor]];
[self assignDelegateForHostCard]; [self assignDelegateForHostCard];
[self.contentView addSubview:self.cardView]; if(!self.cardView.superview){
[NSLayoutConstraint activateConstraints:@[ [self.contentView addSubview:self.cardView];
[self.cardView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor], [NSLayoutConstraint activateConstraints:@[
[self.cardView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:0], [self.cardView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor],
]]; [self.cardView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:0],
]];
}
} }
} }
@@ -69,6 +71,7 @@ static const CGFloat cellOffsetY = 20;
@interface HostCollectionViewController () <UICollectionViewDelegateFlowLayout> @interface HostCollectionViewController () <UICollectionViewDelegateFlowLayout>
@property (nonatomic, strong, readwrite) NSMutableArray<TemporaryHost *> *items; @property (nonatomic, strong, readwrite) NSMutableArray<TemporaryHost *> *items;
@property (nonatomic, strong) NSLayoutConstraint *collectionViewHeightConstraint; @property (nonatomic, strong) NSLayoutConstraint *collectionViewHeightConstraint;
@property (nonatomic, strong) NSLayoutConstraint *superViewBottomConstraint;
@end @end
@implementation HostCollectionViewController{ @implementation HostCollectionViewController{
@@ -129,6 +132,8 @@ static const CGFloat cellOffsetY = 20;
- (void)addHost:(TemporaryHost *)host { - (void)addHost:(TemporaryHost *)host {
if(![self.items containsObject:host]){ if(![self.items containsObject:host]){
[self.items addObject:host];
[self.items addObject:host];
[self.items addObject:host]; [self.items addObject:host];
[self.collectionView reloadData]; [self.collectionView reloadData];
} }
@@ -173,9 +178,10 @@ static const CGFloat cellOffsetY = 20;
CGFloat contentHeight = self.collectionView.collectionViewLayout.collectionViewContentSize.height; CGFloat contentHeight = self.collectionView.collectionViewLayout.collectionViewContentSize.height;
bool contentExceedsView = contentHeight > self.view.superview.bounds.size.height - self.view.frame.origin.y; bool contentExceedsView = contentHeight > self.view.superview.bounds.size.height - self.view.frame.origin.y;
if(contentExceedsView){ if(contentExceedsView){
[NSLayoutConstraint activateConstraints:@[ if(!_superViewBottomConstraint){
[self.view.bottomAnchor constraintEqualToAnchor:self.view.superview.safeAreaLayoutGuide.bottomAnchor constant:0] _superViewBottomConstraint = [self.view.bottomAnchor constraintEqualToAnchor:self.view.superview.safeAreaLayoutGuide.bottomAnchor constant:0];
]]; _superViewBottomConstraint.active = YES;
}
} }
else{ else{
_collectionViewHeightConstraint.constant = contentHeight; _collectionViewHeightConstraint.constant = contentHeight;
@@ -1134,20 +1134,6 @@ static NSMutableSet* hostList;
} }
} }
- (void)handleOrientationChange {
// UIDeviceOrientation targetOrientation = [[UIDevice currentDevice] orientation];
// if([self isIPhone] && UIDeviceOrientationIsPortrait(targetOrientation)) [self simulateSettingsButtonPressClose]; // on iphone, force close settings views if target orietation is portrait.
double delayInSeconds = 0.7;
// Convert the delay into a dispatch_time_t value
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
// Perform some task after the delay
dispatch_after(delayTime, dispatch_get_main_queue(), ^{// Code to execute after the delay
// [self updateResolutionAccordingly];
// [self.settingsButton setEnabled:![self isIPhonePortrait]]; //make sure settings button is disabled in iphone portrait mode.
});
}
// currently obselete: // currently obselete:
- (void) setNeedsUpdateAllowedOrientation{ - (void) setNeedsUpdateAllowedOrientation{
if (@available(iOS 16.0, *)) { if (@available(iOS 16.0, *)) {
@@ -1283,7 +1269,7 @@ static NSMutableSet* hostList;
// Create and configure the label // Create and configure the label
if (@available(iOS 13.0, *)) return; if (@available(iOS 13.0, *)) return;
else { else {
[self->waterMark removeFromSuperview]; [self->waterMark removeFromSuperview]; // removed before activate contraint
self->waterMark = [[UILabel alloc] init]; self->waterMark = [[UILabel alloc] init];
self->waterMark.translatesAutoresizingMaskIntoConstraints = NO; self->waterMark.translatesAutoresizingMaskIntoConstraints = NO;
self->waterMark.numberOfLines = 1; self->waterMark.numberOfLines = 1;
@@ -1426,31 +1412,6 @@ static NSMutableSet* hostList;
return [self isIPhone] ? UINavigationBarHeightIPhone : UINavigationBarHeightIPad; return [self isIPhone] ? UINavigationBarHeightIPhone : UINavigationBarHeightIPad;
} }
- (void)setupHostViewTitle{
self->hostViewTitleLabel = [[UILabel alloc] init];
hostViewTitleLabel.translatesAutoresizingMaskIntoConstraints = NO;
hostViewTitleLabel.numberOfLines = 1;
hostViewTitleLabel.font = [UIFont systemFontOfSize:30 weight:UIFontWeightSemibold];
hostViewTitleLabel.text = [LocalizationHelper localizedStringForKey:@"Hosts"];
// CGFloat labelHeight = 60;
hostViewTitleLabel.textColor = [ThemeManager textColor];
hostViewTitleLabel.textAlignment = NSTextAlignmentCenter;
// hostViewTitleLabel.backgroundColor = [UIColor clearColor];
hostViewTitleLabel.userInteractionEnabled = NO; // Enable user interaction for tap gesture
// Add tap gesture recognizer to handle hyperlink action
[self.view addSubview:hostViewTitleLabel];
// Set up constraints
[NSLayoutConstraint activateConstraints:@[
[hostViewTitleLabel.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:0], // Aligns the horizontal center of label to the horizontal center of view
[hostViewTitleLabel.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:25],
[hostViewTitleLabel.heightAnchor constraintEqualToConstant:30],
[hostViewTitleLabel.widthAnchor constraintEqualToConstant:100],
]];
}
- (void)applyNavBarAppearance{ - (void)applyNavBarAppearance{
if (@available(iOS 13.0, *)) { if (@available(iOS 13.0, *)) {
self.navigationController.navigationBar.standardAppearance.backgroundColor = [UIColor clearColor]; // old ios depend on this, do not remove self.navigationController.navigationBar.standardAppearance.backgroundColor = [UIColor clearColor]; // old ios depend on this, do not remove
@@ -1572,11 +1533,6 @@ static NSMutableSet* hostList;
TemporarySettings* tempSettings = [dataMan getSettings]; TemporarySettings* tempSettings = [dataMan getSettings];
[ThemeManager setUserInterfaceStyle:tempSettings.appTheme.intValue]; [ThemeManager setUserInterfaceStyle:tempSettings.appTheme.intValue];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(deviceOrientationDidChange) // handle orientation change since i made portrait mode available
name:UIDeviceOrientationDidChangeNotification
object:nil];
#if !TARGET_OS_TV #if !TARGET_OS_TV
self.settingsExpandedInStreamView = false; // init this flag self.settingsExpandedInStreamView = false; // init this flag
self.revealViewController.isStreaming = false; //init this flag for rvlVC self.revealViewController.isStreaming = false; //init this flag for rvlVC
@@ -1847,10 +1803,6 @@ static NSMutableSet* hostList;
[self attachWaterMark]; [self attachWaterMark];
#if !TARGET_OS_TV #if !TARGET_OS_TV
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleOrientationChange) // //force expand settings view to update resolution table, and all setting includes current fullscreen resolution will be updated.
name:UIDeviceOrientationDidChangeNotification
object:nil];
[[self revealViewController] setPrimaryViewController:self]; [[self revealViewController] setPrimaryViewController:self];
self.revealViewController.isStreaming = false; // tell the revealViewController streaming is finished self.revealViewController.isStreaming = false; // tell the revealViewController streaming is finished
@@ -2036,20 +1988,6 @@ static NSMutableSet* hostList;
[_discMan resetDiscoveryState]; [_discMan resetDiscoveryState];
} }
// This function forces immediate decoding of the UIImage, rather
// than the default lazy decoding that results in janky scrolling.
-(void)deviceOrientationDidChange{
if(self.revealViewController.isStreaming || self.collectionView.superview == nil) return;
[NSLayoutConstraint activateConstraints:@[
[self.collectionView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
[self.collectionView.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor],
[self.collectionView.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor],
[self.collectionView.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor],
//[self.collectionView.heightAnchor constraintEqualToConstant:_headerViewHeight]
]];
}
+ (UIImage*) loadBoxArtForCaching:(TemporaryApp*)app { + (UIImage*) loadBoxArtForCaching:(TemporaryApp*)app {
UIImage* boxArt; UIImage* boxArt;
@@ -2339,18 +2277,17 @@ static NSMutableSet* hostList;
self.hostCollectionVC.minimumLineSpacing = 25; self.hostCollectionVC.minimumLineSpacing = 25;
// 添加为子控制器 // 添加为子控制器
[self addChildViewController:self.hostCollectionVC]; [self addChildViewController:self.hostCollectionVC];
[self.view addSubview:self.hostCollectionVC.view];
// 设置其布局(Auto Layout 示例) if(self.hostCollectionVC.view.superview == nil){
// CGFloat hostCollectionViewPadding = 75; [self.view addSubview:self.hostCollectionVC.view];
CGFloat leftPadding = [self isIPhone] ? 30 : 0; CGFloat leftPadding = [self isIPhone] ? 30 : 0;
self.hostCollectionVC.view.translatesAutoresizingMaskIntoConstraints = NO; self.hostCollectionVC.view.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint activateConstraints:@[
[self.hostCollectionVC.view.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:0], [self.hostCollectionVC.view.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:0],
[self.hostCollectionVC.view.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor constant:leftPadding], [self.hostCollectionVC.view.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor constant:leftPadding],
[self.hostCollectionVC.view.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor constant:0], [self.hostCollectionVC.view.trailingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor constant:0],
// [self.hostCollectionVC.view.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor constant:0] //? ]];
]]; }
// 通知子控制器已添加完成 // 通知子控制器已添加完成
[self.hostCollectionVC didMoveToParentViewController:self]; [self.hostCollectionVC didMoveToParentViewController:self];
@@ -157,6 +157,13 @@ static CGFloat scaledValue( CGFloat v1, CGFloat min2, CGFloat max2, CGFloat min1
[self insertSubview:_rearNavView belowSubview:_frontView]; [self insertSubview:_rearNavView belowSubview:_frontView];
[self insertSubview:_safeAreaPadding belowSubview:_frontView]; [self insertSubview:_safeAreaPadding belowSubview:_frontView];
[NSLayoutConstraint activateConstraints:@[
[_safeAreaPadding.bottomAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.topAnchor constant:0],
[_safeAreaPadding.topAnchor constraintEqualToAnchor:self.topAnchor],
[_safeAreaPadding.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
[_safeAreaPadding.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
// reserve height for navigation bar
]];
CGFloat navBarHeight = [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone ? UINavigationBarHeightIPhone : UINavigationBarHeightIPad; CGFloat navBarHeight = [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone ? UINavigationBarHeightIPhone : UINavigationBarHeightIPad;
@@ -263,13 +270,6 @@ static CGFloat scaledValue( CGFloat v1, CGFloat min2, CGFloat max2, CGFloat min1
_frontView.layer.shadowPath = shadowPath.CGPath; _frontView.layer.shadowPath = shadowPath.CGPath;
_safeAreaPadding.hidden = self.safeAreaLayoutGuide.topAnchor == 0; _safeAreaPadding.hidden = self.safeAreaLayoutGuide.topAnchor == 0;
[NSLayoutConstraint activateConstraints:@[
[_safeAreaPadding.bottomAnchor constraintEqualToAnchor:self.safeAreaLayoutGuide.topAnchor constant:0],
[_safeAreaPadding.topAnchor constraintEqualToAnchor:self.topAnchor],
[_safeAreaPadding.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
[_safeAreaPadding.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
// reserve height for navigation bar
]];
//NSLog(@"width %f", self.bounds.size.width //NSLog(@"width %f", self.bounds.size.width
} }
@@ -984,7 +984,7 @@ const int FrontViewPositionNone = 0xff;
[_dockedNavBar setItems:@[_navItem]]; [_dockedNavBar setItems:@[_navItem]];
_dockedNavBar.titleTextAttributes = @{NSForegroundColorAttributeName: [UIColor whiteColor]}; _dockedNavBar.titleTextAttributes = @{NSForegroundColorAttributeName: [UIColor whiteColor]};
[_dockedNavBar removeFromSuperview]; [_dockedNavBar removeFromSuperview]; // removed before activate contraints
[_contentView.rearNavView addSubview:_dockedNavBar]; [_contentView.rearNavView addSubview:_dockedNavBar];
// 设置导航栏约束 // 设置导航栏约束
@@ -995,7 +995,7 @@ const int FrontViewPositionNone = 0xff;
[_dockedNavBar.widthAnchor constraintEqualToConstant:_rearViewRevealWidth], [_dockedNavBar.widthAnchor constraintEqualToConstant:_rearViewRevealWidth],
]]; ]];
[self layoutSettingsView]; [self layoutSettingsView];
// NSLog(@"leak test %f %lu", CACurrentMediaTime(), _contentView.rearNavView.constraints.count);
} }
@@ -31,6 +31,7 @@
NSLayoutConstraint *parentStackLeadingConstraint; NSLayoutConstraint *parentStackLeadingConstraint;
NSLayoutConstraint *parentStackWidthConstraint; NSLayoutConstraint *parentStackWidthConstraint;
NSLayoutConstraint *parentStackCenterXConstraint;
NSInteger _bitrate; NSInteger _bitrate;
NSInteger _lastSelectedResolutionIndex; NSInteger _lastSelectedResolutionIndex;
@@ -503,27 +504,18 @@ BOOL isCustomResolution(int resolutionSelected) {
self.scrollView.alwaysBounceVertical = YES; self.scrollView.alwaysBounceVertical = YES;
self.scrollView.showsVerticalScrollIndicator = NO; self.scrollView.showsVerticalScrollIndicator = NO;
/*
self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
// [self.scrollView.topAnchor constraintEqualToAnchor:],
[self.scrollView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.scrollView.topAnchor constraintEqualToAnchor:self.view.topAnchor],
[self.scrollView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
]];
*/
_parentStack = [[UIStackView alloc] init]; _parentStack = [[UIStackView alloc] init];
_parentStack.axis = UILayoutConstraintAxisVertical; _parentStack.axis = UILayoutConstraintAxisVertical;
_parentStack.spacing = 0; _parentStack.spacing = 0;
_parentStack.translatesAutoresizingMaskIntoConstraints = NO; _parentStack.translatesAutoresizingMaskIntoConstraints = NO;
[self.scrollView addSubview:_parentStack];
[NSLayoutConstraint activateConstraints:@[ if(!_parentStack.superview){
[_parentStack.topAnchor constraintEqualToAnchor:self.scrollView.contentLayoutGuide.topAnchor constant: currentSettingsMenuMode == AllSettings ? [self getStandardNavBarHeight] : [self getStandardNavBarHeight]+10], [self.scrollView addSubview:_parentStack];
[_parentStack.bottomAnchor constraintEqualToAnchor:self.scrollView.contentLayoutGuide.bottomAnchor constant:-20], [NSLayoutConstraint activateConstraints:@[
]]; [_parentStack.topAnchor constraintEqualToAnchor:self.scrollView.contentLayoutGuide.topAnchor constant: currentSettingsMenuMode == AllSettings ? [self getStandardNavBarHeight] : [self getStandardNavBarHeight]+10],
[_parentStack.bottomAnchor constraintEqualToAnchor:self.scrollView.contentLayoutGuide.bottomAnchor constant:-20],
]];
}
[self updateParentStackHorizontalConstraints]; [self updateParentStackHorizontalConstraints];
} }
@@ -534,10 +526,10 @@ BOOL isCustomResolution(int resolutionSelected) {
- (void)updateParentStackHorizontalConstraints{ - (void)updateParentStackHorizontalConstraints{
if(![self isIPhone]){ if(![self isIPhone]){
[NSLayoutConstraint activateConstraints:@[ if(parentStackCenterXConstraint && parentStackWidthConstraint) [NSLayoutConstraint deactivateConstraints:@[parentStackCenterXConstraint, parentStackWidthConstraint]];
[_parentStack.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor constant: 0], //mark: settingMenuLayout parentStackCenterXConstraint = [_parentStack.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor constant: 0]; //mark: settingMenuLayout
[_parentStack.widthAnchor constraintEqualToAnchor:self.view.widthAnchor constant:-20] // section width adjusted here parentStackWidthConstraint = [_parentStack.widthAnchor constraintEqualToAnchor:self.view.widthAnchor constant:-20]; // section width adjusted here
]]; [NSLayoutConstraint activateConstraints:@[parentStackCenterXConstraint, parentStackWidthConstraint]];
return; return;
} }
@@ -553,6 +545,7 @@ BOOL isCustomResolution(int resolutionSelected) {
} }
else currentOrientation = keyWindow.windowScene.interfaceOrientation; else currentOrientation = keyWindow.windowScene.interfaceOrientation;
if(parentStackLeadingConstraint && parentStackWidthConstraint) [NSLayoutConstraint deactivateConstraints:@[parentStackLeadingConstraint, parentStackWidthConstraint]];
switch (currentOrientation) { switch (currentOrientation) {
case UIInterfaceOrientationLandscapeRight: case UIInterfaceOrientationLandscapeRight:
parentStackLeadingConstraint = [_parentStack.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor constant:0]; parentStackLeadingConstraint = [_parentStack.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor constant:0];
@@ -568,7 +561,6 @@ BOOL isCustomResolution(int resolutionSelected) {
// Fallback on earlier versions // Fallback on earlier versions
} }
double delayInSeconds = 0.05; double delayInSeconds = 0.05;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^{ dispatch_after(popTime, dispatch_get_main_queue(), ^{
@@ -677,10 +669,10 @@ BOOL isCustomResolution(int resolutionSelected) {
} }
} }
- (void)addSetting:(UIStackView *)stack ofId:(NSString* )identifier withInfoTag:(BOOL)attched withDynamicLabel:(BOOL)added to:(MenuSectionView* )menuSection{ - (void)addSetting:(UIStackView *)stack ofId:(NSString* )identifier withInfoTag:(BOOL)attached withDynamicLabel:(BOOL)added to:(MenuSectionView* )menuSection{
stack.accessibilityIdentifier = identifier; stack.accessibilityIdentifier = identifier;
[_settingStackDict setObject:stack forKey:identifier]; [_settingStackDict setObject:stack forKey:identifier];
if(attched) [self attachInfoTagForStack:stack]; if(attached) [self attachInfoTagForStack:stack];
if(added) [self addDynamicLabelForStack:stack]; if(added) [self addDynamicLabelForStack:stack];
[menuSection addSubStackView:stack]; [menuSection addSubStackView:stack];
} }