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
相关产品推荐
相关产品推荐

