两个UIViewControllers之间的UIPageViewController

时间:2018-05-26 08:53:59

标签: ios swift uiviewcontroller segue uipageviewcontroller

我刚刚开始使用Swift进行编程,我想要完成的是一个非常简单的应用程序,其初始版本为UIViewControllerUIPageViewController显示了一些书页和一个目的地UIViewController

到目前为止,我的方法是:

  1. UIViewController1已加载并且有一个showPage按钮,只显示UIPageViewController
  2. present(walkthroughViewController, animated: true, completion: nil)

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

      寻址segue
      override func onUIPageViewControllerRigthClosing(){
          let pvc = self.presentingViewController as! StartPageController
          dismiss(animated: true){
              pvc.performSegue(withIdentifier: "startTest", sender: nil)
          }
      }
      
    2. 一切正常,但问题是当UIPageViewController被解雇时,显示起始UIViewController,然后显示动画segue的第二个。 我想要实现的是在解除UiViewController时直接向用户显示目标UIPageViewController,而不显示从开始视图到目标视图的动画转换。

      在接近UIPageViewController之前,我是否完全错误接近或有办法解决这个问题?

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

1 个答案:

答案 0 :(得分:0)

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

这是“算法”:

我假设您正在使用包含所有这些视图控制器的单个故事板。

  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. 当您需要在onDoneCallback

  4. 上致电OnboardingViewController时关闭 presentAppContentAfterOnboarding上的
  5. 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)
        })
    }
    
  6. 请注意。不要忘记在故事板中设置OnboardingViewControllerAppContentViewController Storyboard ID

    以下是sample project