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

如何在MainViewController的ContainerView中展示ConceptGalleryViewController?

解决ConceptGalleryViewController无法在MainViewController容器视图中显示的问题

你的问题根源在于两个核心错误:一是直接用performSegue会默认替换整个视图控制器栈,导致侧边菜单消失、画廊全屏显示;二是后来尝试实例化新的MainViewController时,这个新实例的视图还没完成加载,systemContainerView自然是nil,触发了崩溃。

正确的思路是让ConceptViewController通知已存在的MainViewController,由MainViewController负责把ConceptGalleryViewController加载到容器视图里,而不是自己跳转或者创建新的MainVC实例。下面是具体的实现步骤:

第一步:给ConceptViewController添加回调闭包

我们用闭包实现父子控制器间的通信,让ConceptVC能通知MainVC加载画廊:

// ConceptViewController.swift
var onGalleryButtonTapped: ((Int) -> Void)? // 定义闭包,用于传递画廊ID

@IBAction func shareTheFunBtnChecked(_ sender: Any) {
    idGallery = 1
    // 触发闭包,把画廊ID传给MainVC
    onGalleryButtonTapped?(idGallery)
}

第二步:修改MainViewController的容器加载逻辑

先优化showSubViewInContainerView方法,移除容器里已有的子视图和子控制器(避免多个视图重叠),然后在加载ConceptVC的时候绑定闭包:

// MainViewController.swift
func showSubViewInContainerView(view: String){
    // 先清理容器里已有的子控制器和视图
    for childVC in self.children {
        childVC.willMove(toParent: nil)
        childVC.view.removeFromSuperview()
        childVC.removeFromParent()
    }
    
    let targetVC = storyboard!.instantiateViewController(withIdentifier: view)
    addChild(targetVC)
    targetVC.view.translatesAutoresizingMaskIntoConstraints = false
    systemContainerView.addSubview(targetVC.view)
    
    // 绑定约束,让子视图填满容器
    NSLayoutConstraint.activate([
        targetVC.view.leadingAnchor.constraint(equalTo: systemContainerView.leadingAnchor),
        targetVC.view.trailingAnchor.constraint(equalTo: systemContainerView.trailingAnchor),
        targetVC.view.topAnchor.constraint(equalTo: systemContainerView.topAnchor),
        targetVC.view.bottomAnchor.constraint(equalTo: systemContainerView.bottomAnchor)
    ])
    
    // 如果加载的是ConceptVC,绑定闭包
    if let conceptVC = targetVC as? ConceptViewController {
        conceptVC.onGalleryButtonTapped = { [weak self] galleryId in
            // 收到通知后,加载画廊到容器
            self?.showGalleryInContainer(galleryId: galleryId)
        }
    }
    
    targetVC.didMove(toParent: self)
}

第三步:新增加载画廊的专用方法(用于传递ID)

如果需要把idGallery传递给ConceptGalleryViewController,我们可以写一个专用方法:

// MainViewController.swift
func showGalleryInContainer(galleryId: Int) {
    // 同样先清理旧的子视图
    for childVC in self.children {
        childVC.willMove(toParent: nil)
        childVC.view.removeFromSuperview()
        childVC.removeFromParent()
    }
    
    let galleryVC = storyboard!.instantiateViewController(withIdentifier: "ConceptGalleryView") as! ConceptGalleryViewController
    galleryVC.idGallery = galleryId // 传递画廊ID
    
    addChild(galleryVC)
    galleryVC.view.translatesAutoresizingMaskIntoConstraints = false
    systemContainerView.addSubview(galleryVC.view)
    
    // 绑定约束
    NSLayoutConstraint.activate([
        galleryVC.view.leadingAnchor.constraint(equalTo: systemContainerView.leadingAnchor),
        galleryVC.view.trailingAnchor.constraint(equalTo: systemContainerView.trailingAnchor),
        galleryVC.view.topAnchor.constraint(equalTo: systemContainerView.topAnchor),
        galleryVC.view.bottomAnchor.constraint(equalTo: systemContainerView.bottomAnchor)
    ])
    
    galleryVC.didMove(toParent: self)
}

为什么之前的代码会崩溃?

你之前实例化了新的MainViewController:

let viewController = self.storyboard?.instantiateViewController(withIdentifier: "MainView") as! MainViewController

这个新实例的view还没有被系统加载(未调用viewDidLoad),所以systemContainerView这个IBOutlet还未初始化,自然是nil,调用viewController.systemContainerView.addSubview就会触发崩溃。我们要复用的是当前已经显示在屏幕上的MainVC实例,而不是新建一个。

这样修改后,点击ConceptVC里的按钮,就会通知MainVC把GalleryVC加载到容器视图里,侧边菜单也会保留,完全符合你的布局需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:36:37