两个 UIViewController 之间的 UIPageViewController

UIPageViewController between two UIViewControllers

我刚开始在 Swift 中编程,我想要完成的是一个非常简单的应用程序,它有一个初始 UIViewController,一个显示一些书页的 UIPageViewController和目的地 UIViewController.

到目前为止我的方法是这样的:

  1. UIViewController1 已加载并有一个仅显示 UIPageViewController
  2. 的 showPage 按钮

present(walkthroughViewController, animated: true, completion: nil)

  1. 当用户到达UIPageViewController的最后一页时,我显示目的地UIViewController2,从头开始解决segue UIViewController

    override func onUIPageViewControllerRigthClosing(){
        let pvc = self.presentingViewController as! StartPageController
        dismiss(animated: true){
            pvc.performSegue(withIdentifier: "startTest", sender: nil)
        }
    }
    

一切正常,但问题是当 UIPageViewController 被关闭时,开始 UIViewController 显示,然后显示第二个动画 segue。 我想要实现的是在 UIPageViewController 关闭时直接向用户显示目标 UiViewController,而不显示从开始视图到目标视图的动画过渡。

我完全错了,或者有办法在关闭 UIPageViewController?

之前进行转场

我在这里创建了一个显示问题的 gif,当我关闭 UIPageViewController 我看到之前的视图正在转换:GIF demo

我建议您使用这种方法:对于这些屏幕转换,使用 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()
        })
    }
}

这是"algorithm":

我假设您使用的是带有所有这些视图控制器的单个故事板。

  1. OnBoardingViewController 声明 onDoneCallback:

    class OnBoardingViewController: ... {
        var onDoneCallback = {}
        ...
    }
    
  2. RootViewController 需要礼物时 OnboardingViewController:

    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
        })
    }
    
  3. 当您需要在 OnboardingViewController

  4. 上调用 onDoneCallback 闭包时
  5. presentAppContentAfterOnboarding RootViewController 上的方法可能如下所示:

    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)
        })
    }
    

注意。不要忘记在故事板中设置 故事板 ID of OnboardingViewControllerAppContentViewController

这是sample project