如何在 UIScrollView 中调用嵌入式 ViewControllers 生命周期 - Swift - 以编程方式
How to call embedded ViewControllers lifecycles in UIScrollView - Swift - Programmatically
我正在创建一个能够依次显示 ViewController 个视图的滚动视图。这是我实现的代码:
scrollView.contentSize = CGSize(width: screenWidth * 3, height: screenHeight)
let firstVC = FirstViewController()
let secondVC = SecondViewController()
let thirdVC = ThirdViewController()
self.addChild(firstVC)
self.scrollView.addSubview(firstVC.view)
firstVC.willMove(toParent: self)
self.addChild(secondVC)
self.scrollView.addSubview(secondVC.view)
secondVC.willMove(toParent: self)
self.addChild(thirdVC)
self.scrollView.addSubview(thirdVC.view)
thirdVC.willMove(toParent: self)
firstVC.view.frame.origin = CGPoint.zero
secondVC.view.frame.origin = CGPoint(x: screenWidth, y: 0)
thirdVC.view.frame.origin = CGPoint(x: screenWidth*2, y: 0)
view.addSubview(scrollView)
scrollView.fillSuperview()
我想知道是否可以在滚动时调用每个 ViewController 生命周期方法。
例如,当我从 vc1 传递到 vc2 时,我想要的是:
vc1 触发 viewwillDisappear 方法
vc2 触发 viewWillAppear 方法
最简单的解决方案是使用页面视图控制器。当你这样做时,子项的外观方法将自动为你调用(它让你摆脱所有那些手动填充和配置滚动视图的密集代码):
class MainViewController: UIPageViewController {
let controllers = [RedViewController(), GreenViewController(), BlueViewController()]
override func viewDidLoad() {
super.viewDidLoad()
dataSource = self
setViewControllers([controllers.first!], direction: .forward, animated: true, completion: nil)
}
}
extension MainViewController: UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
if let index = controllers.firstIndex(where: { [=10=] == viewController }), index < (controllers.count - 1) {
return controllers[index + 1]
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
if let index = controllers.firstIndex(where: { [=10=] == viewController }), index > 0 {
return controllers[index - 1]
}
return nil
}
}
如果您真的想使用滚动视图方法,请不要预先执行视图控制器包含代码,而是只在它们滚动到视图中时添加它们(并在它们滚动出视图时删除它们)。您只需要为滚动视图设置一个委托并实现一个 UIScrollViewDelegate
方法。
因此,例如,我可能只使用这三个子视图控制器的容器子视图填充我的滚动视图。 (注意下面示例中的 containerViews
只是空白的 UIView
实例,布置在子视图控制器视图最终将到达的位置。)然后我可以查看 CGRect
的可见部分是否滚动视图与容器视图相交,并以 just-in-time 方式包含视图控制器。
extension ViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let rect = CGRect(origin: scrollView.contentOffset, size: scrollView.bounds.size)
for (index, containerView) in containerViews.enumerated() {
let controller = controllers[index]
let controllerView = controller.view!
if rect.intersects(containerView.frame) {
if controllerView.superview == nil {
// a container view has scrolled into view, but the associated
// child controller view has not been added to the view hierarchy, yet
// so let's do that now
addChild(controller)
containerView.addSubview(controllerView)
controllerView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
controllerView.topAnchor.constraint(equalTo: containerView.topAnchor),
controllerView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor),
controllerView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
controllerView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor)
])
controller.didMove(toParent: self)
}
} else {
if controllerView.superview != nil {
// a container view has scrolled out of view, but the associated
// child controller view is still in the view hierarchy, so let's
// remove it.
controller.willMove(toParent: nil)
controllerView.removeFromSuperview()
controller.removeFromParent()
}
}
}
}
}
在这两种情况下,您都会在视图出现时收到遏制电话。
我正在创建一个能够依次显示 ViewController 个视图的滚动视图。这是我实现的代码:
scrollView.contentSize = CGSize(width: screenWidth * 3, height: screenHeight)
let firstVC = FirstViewController()
let secondVC = SecondViewController()
let thirdVC = ThirdViewController()
self.addChild(firstVC)
self.scrollView.addSubview(firstVC.view)
firstVC.willMove(toParent: self)
self.addChild(secondVC)
self.scrollView.addSubview(secondVC.view)
secondVC.willMove(toParent: self)
self.addChild(thirdVC)
self.scrollView.addSubview(thirdVC.view)
thirdVC.willMove(toParent: self)
firstVC.view.frame.origin = CGPoint.zero
secondVC.view.frame.origin = CGPoint(x: screenWidth, y: 0)
thirdVC.view.frame.origin = CGPoint(x: screenWidth*2, y: 0)
view.addSubview(scrollView)
scrollView.fillSuperview()
我想知道是否可以在滚动时调用每个 ViewController 生命周期方法。
例如,当我从 vc1 传递到 vc2 时,我想要的是:
vc1 触发 viewwillDisappear 方法
vc2 触发 viewWillAppear 方法
最简单的解决方案是使用页面视图控制器。当你这样做时,子项的外观方法将自动为你调用(它让你摆脱所有那些手动填充和配置滚动视图的密集代码):
class MainViewController: UIPageViewController {
let controllers = [RedViewController(), GreenViewController(), BlueViewController()]
override func viewDidLoad() {
super.viewDidLoad()
dataSource = self
setViewControllers([controllers.first!], direction: .forward, animated: true, completion: nil)
}
}
extension MainViewController: UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
if let index = controllers.firstIndex(where: { [=10=] == viewController }), index < (controllers.count - 1) {
return controllers[index + 1]
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
if let index = controllers.firstIndex(where: { [=10=] == viewController }), index > 0 {
return controllers[index - 1]
}
return nil
}
}
如果您真的想使用滚动视图方法,请不要预先执行视图控制器包含代码,而是只在它们滚动到视图中时添加它们(并在它们滚动出视图时删除它们)。您只需要为滚动视图设置一个委托并实现一个 UIScrollViewDelegate
方法。
因此,例如,我可能只使用这三个子视图控制器的容器子视图填充我的滚动视图。 (注意下面示例中的 containerViews
只是空白的 UIView
实例,布置在子视图控制器视图最终将到达的位置。)然后我可以查看 CGRect
的可见部分是否滚动视图与容器视图相交,并以 just-in-time 方式包含视图控制器。
extension ViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let rect = CGRect(origin: scrollView.contentOffset, size: scrollView.bounds.size)
for (index, containerView) in containerViews.enumerated() {
let controller = controllers[index]
let controllerView = controller.view!
if rect.intersects(containerView.frame) {
if controllerView.superview == nil {
// a container view has scrolled into view, but the associated
// child controller view has not been added to the view hierarchy, yet
// so let's do that now
addChild(controller)
containerView.addSubview(controllerView)
controllerView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
controllerView.topAnchor.constraint(equalTo: containerView.topAnchor),
controllerView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor),
controllerView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
controllerView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor)
])
controller.didMove(toParent: self)
}
} else {
if controllerView.superview != nil {
// a container view has scrolled out of view, but the associated
// child controller view is still in the view hierarchy, so let's
// remove it.
controller.willMove(toParent: nil)
controllerView.removeFromSuperview()
controller.removeFromParent()
}
}
}
}
}
在这两种情况下,您都会在视图出现时收到遏制电话。