You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UIKit 中被隐藏的视图是否会对应用内存造成压力?

问题描述

我有一个父视图存在多种不同状态,分别对应展示等待动画、倒计时、录制界面等场景,每个状态都对应父视图的一个直接子视图:
视图层级示意图
我的实现思路是定义一个状态变量,通过属性观察器来仅展示对应状态的子视图,示例代码如下:

enum Status {
    case waiting
    case countDown
    // ...
}

var status: Status = .loading { didSet { showRelevantView() } }

func showRelevantView() {
    waitingView.isHidden = status != .waiting
    countDownView.isHidden = status != .countDown
    // ...
}

按照上述逻辑实现后,6个子视图同一时间只会有1个处于展示状态,其余5个均被设置为隐藏。我想了解这5个被隐藏的子视图是否会对应用内存造成压力,如果存在内存问题,有什么合适的优化方案?

解答

隐藏视图的内存占用说明

  • 只要子视图还被强引用持有、且保留在父视图的层级中,哪怕设置了isHidden = true,依旧会占用内存
  • 如果你的6个子视图都是轻量视图(仅包含普通文本、按钮、小尺寸图标),总内存占用通常只有几KB到几十KB,完全不会造成内存压力,现有实现无需修改
  • 如果部分子视图包含大尺寸资源、视频预览层、实时动画、大量渲染图层,隐藏状态下这些资源依旧会驻留内存,累计下来可能造成不必要的内存占用,就需要做优化

常用优化方案

  • 方案1:按需添加/移除视图(最通用)
    不要提前初始化所有子视图并添加到父视图,仅在状态切换时做如下操作:
// 记录当前正在展示的视图
private weak var currentShowingView: UIView?

func showRelevantView() {
    // 先移除当前正在展示的旧视图
    currentShowingView?.removeFromSuperview()
    // 根据状态获取对应视图,不常用的视图可以设为懒加载,首次使用才初始化
    var targetView: UIView?
    switch status {
    case .waiting:
        targetView = waitingView
    case .countDown:
        targetView = countDownView
    // ...其他状态处理
    default: break
    }
    guard let targetView = targetView else { return }
    // 添加新视图到父视图
    parentView.addSubview(targetView)
    // 适配布局,这里以SnapKit为例,也可以用frame或系统约束
    targetView.snp.makeConstraints { make in
        make.edges.equalToSuperview()
    }
    currentShowingView = targetView
}
  • 方案2:子控制器拆分管理
    如果每个状态对应的业务逻辑比较复杂,可以把每个状态的视图和逻辑封装到独立的UIViewController中,通过父控制器的子控制器管理API来控制生命周期,逻辑拆分更清晰,系统会自动触发子控制器的生命周期回调:
private weak var currentChildVC: UIViewController?

func showRelevantController() {
    // 移除旧的子控制器
    currentChildVC?.willMove(toParent: nil)
    currentChildVC?.view.removeFromSuperview()
    currentChildVC?.removeFromParent()
    // 加载对应新的子控制器
    let targetVC = // 根据状态获取对应子控制器实例
    addChild(targetVC)
    view.addSubview(targetVC.view)
    targetVC.view.snp.makeConstraints { make in make.edges.equalToSuperview() }
    targetVC.didMove(toParent: self)
    currentChildVC = targetVC
}
  • 方案3:缓存池方案(适合频繁切换场景)
    如果状态切换非常频繁,每次创建销毁视图开销过大,可以维护一个最大容量的缓存池,缓存最近使用的2-3个视图,超出容量的视图自动释放,平衡内存占用和加载速度。

内容的提问来源于stack exchange,提问作者Dannis Case

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 06:45:06