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

Swift如何依次加载视图控制器?无按钮自动跳转实现

问题:无需按钮触发,自动从第一个视图控制器跳转至第二个

我希望以编程方式先加载第一个视图控制器SLLoadingViewController,再自动从它加载嵌套在导航控制器中的StoreViewController。

现有失效代码

SceneDelegate 代码

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        
        if let windowScene = (scene as? UIWindowScene) {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = SLLoadingViewController()
            self.window = window
            window.makeKeyAndVisible()
        }
    }

SLLoadingViewController 自动跳转代码(失效)

override func viewDidLoad() {
    super.viewDidLoad()
    load()
}

func load() {
    
    let nav = SLNavigationViewController()
    let mainView = StoreViewController()
    nav.navigationBar.frame.size = nav.navigationBar.sizeThatFits(CGSize(width: nav.navigationBar.frame.size.width, height: 2))
    nav.viewControllers = [mainView]
    
    present(nav, animated: false, completion: nil)
}

这段代码无法生效,最终的StoreViewController无法显示在屏幕上,但通过按钮触发的代码可以正常运行:

按钮触发的有效代码

override func viewDidLoad() {
    super.viewDidLoad()
    button.frame = CGRect(x: 100, y: 200, width: 30, height: 20)
    button.backgroundColor = .green
    view.addSubview(button)
    button.addTarget(self, action: #selector(self.load), for: .touchUpInside) 
}

@objc func load() {
    
    let nav = SLNavigationViewController()
    let mainView = StoreViewController()
    nav.navigationBar.frame.size = nav.navigationBar.sizeThatFits(CGSize(width: nav.navigationBar.frame.size.width, height: 2))
    nav.viewControllers = [mainView]
    
    present(nav, animated: false, completion: nil)
}

解决方案

问题出在viewDidLoad阶段,此时视图控制器的视图还未完成布局和显示,调用present无法正确触发跳转。可以通过以下几种方式解决:

方法1:移至viewDidAppear执行

将跳转逻辑放到viewDidAppear方法中,确保视图已经完全显示后再执行跳转:

override func viewDidLoad() {
    super.viewDidLoad()
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    load()
}

func load() {
    let nav = SLNavigationViewController()
    let mainView = StoreViewController()
    nav.navigationBar.frame.size = nav.navigationBar.sizeThatFits(CGSize(width: nav.navigationBar.frame.size.width, height: 2))
    nav.viewControllers = [mainView]
    
    present(nav, animated: false, completion: nil)
}

方法2:延迟执行跳转逻辑

如果不想等待viewDidAppear,可以在viewDidLoad中延迟调用跳转方法,给视图足够的初始化时间:

override func viewDidLoad() {
    super.viewDidLoad()
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
        self.load()
    }
}

func load() {
    let nav = SLNavigationViewController()
    let mainView = StoreViewController()
    nav.navigationBar.frame.size = nav.navigationBar.sizeThatFits(CGSize(width: nav.navigationBar.frame.size.width, height: 2))
    nav.viewControllers = [mainView]
    
    present(nav, animated: false, completion: nil)
}

方法3:直接替换根控制器(更高效)

如果不需要保留SLLoadingViewController,可以直接替换窗口的根控制器,无需使用present:

func load() {
    let nav = SLNavigationViewController()
    let mainView = StoreViewController()
    nav.navigationBar.frame.size = nav.navigationBar.sizeThatFits(CGSize(width: nav.navigationBar.frame.size.width, height: 2))
    nav.viewControllers = [mainView]
    
    if let window = UIApplication.shared.windows.first {
        window.rootViewController = nav
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 16:42:34