[英]UIPageViewController between two UIViewControllers
I've just started programming in Swift, what I'm trying to accomplish is a very simple app with an initial UIViewController
, a UIPageViewController
that shows some book pages and a destination UIViewController
. 我刚刚开始用Swift进行编程,我想要完成的是一个非常简单的应用程序,带有一个初始UIViewController
,一个显示一些书页的UIPageViewController
和一个目标UIViewController
。
My approach so far is this: 到目前为止,我的方法是:
UIViewController1
is loaded and has a showPage button that simply shows UIPageViewController
UIViewController1
已加载并具有一个showPage按钮,该按钮仅显示UIPageViewController
present(walkthroughViewController, animated: true, completion: nil)
When the user reaches the last page of the UIPageViewController
, I show the destination UIViewController2
, addressing the segue from the start UIViewController
当用户到达UIPageViewController
的最后一页时,我将显示目标UIViewController2
,从开始的UIViewController
处理UIPageViewController
override func onUIPageViewControllerRigthClosing(){ let pvc = self.presentingViewController as! StartPageController dismiss(animated: true){ pvc.performSegue(withIdentifier: "startTest", sender: nil) } }
Everything works correctly, but the problem is that when UIPageViewController
is dismissed, the Starting UIViewController
is showed and then is showed the second with the animated segue. 一切正常,但是问题在于,当UIPageViewController
时,将显示“启动UIViewController
,然后显示第二个带有动画的序列。 What I am trying to achieve is to directly display the target UiViewController
to the user on the dismiss of the UIPageViewController
, without showing the transition with animation from start View to the destination View. 我想要实现的是在关闭UiViewController
直接向用户显示目标UIPageViewController
,而不显示从开始View到目标View的动画过渡。
I'm completely wrong approaching or there is a way to do the segue before dismissing the UIPageViewController
? 我的做法完全错误,或者有办法在关闭UIPageViewController
之前执行segue吗?
Here I created a gif that shows the problem, when I close the UIPageViewController
I see the previous view in transition: GIF demo 在这里,我创建了一个gif来显示问题,当我关闭UIPageViewController
我看到了转换中的前一个视图: GIF演示
I suggest you using this approach: for these screens transitions use childViewControllers instead of presenting them modally and dismissing with default UIKit functions. 我建议您使用这种方法:对于这些屏幕过渡,请使用childViewControllers而不是以模态方式呈现它们并使用默认的UIKit函数关闭。
You have problems with naming, so let me rename view controllers. 您在命名时遇到问题,所以让我重命名视图控制器。 Say, you have: 说,您有:
RootViewController
(the first screen, user see after app launch). RootViewController
(第一个屏幕,用户在应用启动后查看)。 OnboardingViewController
(your pageViewController or other container) OnboardingViewController
(您的pageViewController或其他容器) AppContentViewController
(actually app main screen) AppContentViewController
(实际上是应用程序主屏幕) I suggest you using this approach: for screens transitions on RootViewController
use childViewControllers instead of presenting them modally and dismissing with default UIKit functions. 我建议您使用这种方法:对于RootViewController
上的屏幕过渡,请使用childViewControllers而不是以模态方式呈现它们并使用默认的UIKit函数关闭。
Here is sample code that works with childViewControllers 这是与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()
})
}
}
Here is "algorithm": 这是“算法”:
I assuming that you are using single storyboard with all these view controllers. 我假设您将所有这些视图控制器都使用单个情节提要。
On OnBoardingViewController
declare onDoneCallback
: 在OnBoardingViewController
声明onDoneCallback
:
class OnBoardingViewController: ... { var onDoneCallback = {} ... }
On RootViewController
when you need present OnboardingViewController
: 在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 }) }
When you need call onDoneCallback
closure on OnboardingViewController
当您需要在OnboardingViewController
上调用onDoneCallback
关闭时
presentAppContentAfterOnboarding
method on RootViewController
could look like: 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) }) }
Note. 注意。 Don't forget to set Storyboard ID of OnboardingViewController
and AppContentViewController
in your storyboard. 不要忘记在情节提要中设置OnboardingViewController
和AppContentViewController
的情节提要ID 。
Here is the sample project 这是示例项目
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.