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

Swift UIPageViewController触发Window should be nonnil断言且内容不显示

问题复现

当PageController尝试展示其内容时,控制台输出如下断言提示:

"[Assert] Window should be nonnil here unless a subclass is mistakenly sending this to a child when no window can be found"

应用未崩溃,但PageController对应内容无法正常显示,业务代码实现如下:

class RulesPageViewController: UIPageViewController {

    var rulesDelegate: RulesPageVeiwControllerDelegate?
    
    var pageHeadings = ["1st page","2nd","3rd"]
    
    var currentIndex = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()

        self.dataSource = self
        self.delegate = self
        
        if let startingViewController = contentViewController(at: 0)
        {
            self.setViewControllers([startingViewController], direction: .forward, animated: false, completion: nil)
        }
    }
    

    func contentViewController(at index: Int)-> PageContentViewController?
    {
        if(index < 0 || index >= pageHeadings.count)
        {
            return nil
        }
        if let pageContentViewController = UIStoryboard(name: "GameRules", bundle: nil).instantiateViewController(withIdentifier: "PageContentViewController") as? PageContentViewController{
            pageContentViewController.index = index
            return pageContentViewController
        }
        return nil
    }

}
extension RulesPageViewController: UIPageViewControllerDelegate {
    
    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
        
        if completed {
            if let contentViewController = pageViewController.viewControllers?.first as? PageContentViewController
            {
                currentIndex = contentViewController.index
                rulesDelegate?.didUpdatePageIndex(currentIndex: currentIndex)
            }
        }
    }
}

extension RulesPageViewController: UIPageViewControllerDataSource {
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        var index = (viewController as! PageContentViewController).index
        index -= 1
        return contentViewController(at: index)
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        var index = (viewController as! PageContentViewController).index
        index += 1
        return contentViewController(at: index)
    }
}
原因说明

该断言触发的核心原因是viewDidLoad执行时,UIPageViewController的视图尚未挂载到App的window层级上,此时调用setViewControllers会触发系统内部的非空校验失败。

解决方案
  • 调整初始控制器设置的执行时机:将viewDidLoad中的初始控制器设置逻辑迁移到viewDidAppear(_:)中,添加标识避免重复执行:
// 新增属性标记初始控制器是否已设置
private var isInitialPageSet = false

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    guard !isInitialPageSet else { return }
    if let startingViewController = contentViewController(at: 0) {
        self.setViewControllers([startingViewController], direction: .forward, animated: false, completion: nil)
    }
    isInitialPageSet = true
}
  • 如果需要更早执行设置,可替换为viewWillAppear(_:)方法,绝大多数场景下此时视图已关联到window,不会触发断言。
  • 额外校验:如果是代码初始化的RulesPageViewController,确认使用的是指定初始化方法init(transitionStyle:navigationOrientation:options:),而非默认的init(nibName:bundle:),初始化参数配置错误也会触发该问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 03:54:08