基于TableView选择结果在Container View中嵌入ViewController
动态切换Container View内容的实现方案
首先得明确:原来的Embed Segue是静态绑定的,要实现动态切换,我们需要手动管理Container里的子控制器,同时保留父控制器的页眉页脚(因为页眉页脚属于父控制器,只要不替换父控制器就不会丢失)。下面是亲测可行的具体步骤:
1. 准备工作:调整Storyboard & 定义属性
- 给Container View对应的Embed Segue设置一个标识符(比如
EmbedInitialTableVC),方便父控制器捕获初始的子控制器。 - 在包含Container View的父控制器(假设叫
MainContainerVC)中,添加属性来持有当前显示的子控制器:class MainContainerVC: UIViewController { // 关联Storyboard里的Container View @IBOutlet weak var containerView: UIView! // 持有当前显示的子控制器 private var currentChildVC: UIViewController? }
2. 捕获初始的TableViewController
在父控制器的prepare(for:sender:)方法中,获取通过Embed Segue进来的TableVC,并存到currentChildVC里,同时设置选择回调:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "EmbedInitialTableVC" { // 假设你的TableVC叫TableListVC guard let tableVC = segue.destination as? TableListVC else { return } currentChildVC = tableVC // 设置选择回调,让TableVC能通知父控制器切换内容 tableVC.onSelection = { [weak self] selectedType in self?.switchToChildVC(with: selectedType) } } }
3. 在TableViewController里添加选择回调
给你的TableVC定义一个闭包,用来传递用户的选择事件:
class TableListVC: UITableViewController { // 定义回调闭包,参数可根据你的需求调整(比如用字符串区分选项) var onSelection: ((String) -> Void)? override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) // 假设第0行是“地图”选项 if indexPath.row == 0 { onSelection?("map") } // 可添加其他选项的判断,比如切换回列表等 } }
4. 实现子控制器的切换逻辑
在父控制器里写一个核心方法,负责移除旧控制器、添加新控制器到Container中:
private func switchToChildVC(with type: String) { // 1. 移除当前的子控制器 currentChildVC?.willMove(toParent: nil) currentChildVC?.view.removeFromSuperview() currentChildVC?.removeFromParent() // 2. 根据选择创建对应的新控制器 let newChildVC: UIViewController if type == "map" { // 从Storyboard初始化MapViewController(记得给它设置storyboardID) newChildVC = storyboard?.instantiateViewController(withIdentifier: "MapViewController") as! MapViewController } else { // 如果是回到列表,重新初始化TableVC并设置回调 newChildVC = storyboard?.instantiateViewController(withIdentifier: "TableListVC") as! TableListVC (newChildVC as? TableListVC)?.onSelection = { [weak self] selectedType in self?.switchToChildVC(with: selectedType) } } // 3. 将新控制器添加为父控制器的子控制器 addChild(newChildVC) newChildVC.view.frame = containerView.bounds // 设置自动适配Container的尺寸变化 newChildVC.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] containerView.addSubview(newChildVC.view) newChildVC.didMove(toParent: self) // 4. 更新当前子控制器的引用 currentChildVC = newChildVC }
5. 适配Container View的尺寸变化
如果父控制器布局会变化(比如屏幕旋转),要确保子控制器的view跟着调整,在父控制器中重写:
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() currentChildVC?.view.frame = containerView.bounds }
这样操作后,当你在TableVC里选择“地图”选项时,Container View就会无缝切换到MapViewController,而父控制器的页眉页脚会一直保留,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Voque
相关产品推荐
相关产品推荐

