1

我正在创建一个滚动视图,它能够一个接一个地显示 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 方法

4

1 回答 1

1

最简单的解决方案是使用页面视图控制器。当您这样做时,将自动为您调用子项的外观方法(它使您摆脱所有密集的代码来手动填充和配置滚动视图):

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: { $0 == 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: { $0 == viewController }), index > 0 {
            return controllers[index - 1]
        }
        return nil
    }
}

如果您真的想使用滚动视图方法,请不要预先执行视图控制器包含代码,而仅在它们滚动到视图时添加它们(并在它们滚动到视图之外时将它们删除)。你只需要为你的滚动视图设置一个委托并实现一个UIScrollViewDelegate方法。

因此,例如,我可能只使用这三个子视图控制器的容器子视图填充我的滚动视图。(请注意containerViews,在下面的示例中只是空白UIView实例,布置了子视图控制器视图最终将去的位置。)然后我可以查看CGRect滚动视图的可见部分是否与容器视图相交,并执行视图控制器包含以及时的方式。

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

在这两种情况下,您都会在视图出现时收到包含调用。

于 2020-09-11T04:59:27.583 回答