Swift:通过侧边菜单切换时保留已实例化的视图控制器
复用已实例化的视图控制器实现侧边菜单跳转
嘿,这个需求太常见了——每次点击菜单都重新创建控制器不仅浪费资源,还可能丢失之前的页面状态,用缓存已实例化的控制器就能完美解决。我给你整理了一套可直接复用的实现方案:
核心思路
用一个容器(数组/字典)存储已经创建过的控制器实例,每次点击菜单时先检查缓存:
- 如果缓存里有对应的控制器,直接复用
- 如果没有,创建新实例并存入缓存,再进行跳转
具体代码实现
1. 声明缓存容器
在你的侧边菜单控制器(UITableViewController子类)里,添加一个私有数组用来缓存控制器:
private var viewControllerCache: [UIViewController?] = []
2. 初始化缓存占位
在viewDidLoad里根据你的菜单选项数量初始化缓存数组(用nil占位,后续创建后替换):
override func viewDidLoad() { super.viewDidLoad() // 这里的3替换成你侧边菜单的选项总数 viewControllerCache = Array(repeating: nil, count: 3) }
3. 修改单元格点击事件
更新tableView(_:didSelectRowAt:)方法,加入缓存判断逻辑:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { self.tableView.deselectRow(at: indexPath, animated: true) // 先从缓存中获取目标控制器 var targetVC: UIViewController? = viewControllerCache[indexPath.row] // 缓存为空时,创建新实例并缓存 if targetVC == nil { switch indexPath.row { case 0: targetVC = LaunchViewController() // 替换成你的第一个控制器类 targetVC?.title = "启动页" case 1: targetVC = SettingsViewController() // 第二个控制器 targetVC?.title = "设置" case 2: targetVC = ProfileViewController() // 第三个控制器 targetVC?.title = "个人中心" // 按需添加更多菜单选项的case default: return } // 将新创建的控制器存入缓存 viewControllerCache[indexPath.row] = targetVC } // 确保控制器存在,推入导航栈(避免重复push同一控制器) if let vc = targetVC, navigationController?.topViewController !== vc { navigationController?.pushViewController(vc, animated: true) } }
额外优化建议
- 如果你的菜单选项是动态生成的(比如从服务器获取),可以用字典替代数组,以控制器的唯一标识(比如类型名、自定义ID)作为key,这样更灵活。
- 如果控制器需要接收动态参数,记得在第一次创建时传入;后续复用若需要更新参数,可以在push前重新设置控制器的属性。
- 若控制器占用内存较大,可在
didReceiveMemoryWarning方法中清理不常用的缓存实例,避免内存泄漏:
override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // 清理所有缓存(或按需清理特定索引的缓存) viewControllerCache = Array(repeating: nil, count: viewControllerCache.count) }
内容的提问来源于stack exchange,提问作者phoebus
相关产品推荐
相关产品推荐

