我建议您使用这种方法:对于这些屏幕转换使用 childViewControllers 而不是模态显示它们并使用默认的 UIKit 函数关闭。
你有命名的问题,所以让我重命名视图控制器。
说,你有:
-
RootViewController(第一屏,用户看后
应用程序启动)。
-
OnboardingViewController(您的 pageViewController 或其他容器)
-
AppContentViewController(其实是应用主屏)
我建议您使用这种方法:对于RootViewController 上的屏幕转换,使用 childViewControllers 而不是模态显示它们并使用默认的 UIKit 函数关闭。
这是与 childViewControllers 一起使用的示例代码
extension UIViewController {
func displayChildController(_ content: UIViewController, duration: TimeInterval = 0.4, animation: (() -> ())? = nil, completion: @escaping () -> () = {}) {
content.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height)
view.addSubview(content.view)
addChildViewController(content)
UIView.animate(withDuration: animation != nil ? duration : 0, animations: {() -> Void in
animation?()
}, completion: {(_ finished: Bool) -> Void in
content.didMove(toParentViewController: self)
completion()
})
}
func hideChildController(_ content: UIViewController, duration: TimeInterval = 0.4, animation: (() -> ())? = nil, completion: @escaping () -> () = {}) {
UIView.animate(withDuration: animation != nil ? duration : 0, animations: {() -> Void in
animation?()
}, completion: {(_ finished: Bool) -> Void in
content.willMove(toParentViewController: nil)
content.view.removeFromSuperview()
content.removeFromParentViewController()
completion()
})
}
}
这里是“算法”:
我假设您将单个故事板与所有这些视图控制器一起使用。
-
在OnBoardingViewController 上声明onDoneCallback:
class OnBoardingViewController: ... {
var onDoneCallback = {}
...
}
-
当你需要出席OnboardingViewController时打开RootViewController:
func presentOnboardingScreen() {
let onboardingVC = self.storyboard?.instantiateViewController(withIdentifier: "OnboardingViewController") as! OnboardingViewController
onboardingVC.transform = .init(translationX: 0, y: self.view.frame.height)
onboardingVC.onDoneCallback = {
self.presentAppContentAfterOnboarding() // see below
}
displayChildController(onboardingVC, duration: 0.3, animation: {
vc.view.transform = .identity
})
}
当您需要调用 onDoneCallback 关闭 OnboardingViewController
-
RootViewController 上的presentAppContentAfterOnboarding 方法可能如下所示:
func presentAppContentAfterOnboarding() {
let onboardingVC = self.childViewControllers.last as! OnboardingViewController
let appContentVC = self.storyboard?.instantiateViewController(withIdentifier: "AppContentViewController") as! AppContentViewController
displayChildController(appContentVC)
view.insertSubview(appContentVC.view, belowSubview: onboardingVC.view)
hideChildController(childVC, duration: duration, animation: {
onboardingVC.view.transform = .init(translationX: 0, y: self.view.frame.height)
})
}
注意。不要忘记在您的故事板中设置OnboardingViewController 和AppContentViewController 的故事板ID。
这里是sample project