Как добавить UIPageViewController в UIStackView (внутри UIScrollView)

#ios #swift #uikit

Вопрос:

Я пытаюсь добавить UIPageViewController в UIStackView внутри UIScrollView, но все, что я вижу, — это пустое пространство (высотой 200 пикселей), где должен быть UIPageViewController.

Мой код выглядит следующим образом:

 class ViewController: UIViewController {
    var scrollView: UIScrollView!
    var pageViewController: UIPageViewController!
    var controllers: [UIViewController] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        scrollView = UIScrollView()
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(scrollView)
        
        let frameLayoutGuide = scrollView.frameLayoutGuide
        frameLayoutGuide.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
        frameLayoutGuide.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
        frameLayoutGuide.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        frameLayoutGuide.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true

        let contentLayoutGuide = scrollView.contentLayoutGuide
        contentLayoutGuide.widthAnchor.constraint(equalTo: frameLayoutGuide.widthAnchor).isActive = true
        
        let contentView = UIStackView()
        contentView.translatesAutoresizingMaskIntoConstraints = false
        contentView.axis = .vertical
        scrollView.addSubview(contentView)
        
        contentLayoutGuide.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
        contentLayoutGuide.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
        contentLayoutGuide.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
        contentLayoutGuide.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
        
        // ---
        
        let view1 = UIView()
        view1.translatesAutoresizingMaskIntoConstraints = false
        view1.heightAnchor.constraint(equalToConstant: 250).isActive = true
        view1.backgroundColor = .red
        contentView.addArrangedSubview(view1)
        
        //
        
        let controller1 = UIViewController()
        controller1.view.backgroundColor = .black
        controllers.append(controller1)

        let controller2 = UIViewController()
        controller2.view.backgroundColor = .darkGray
        controllers.append(controller2)
        
        let controller3 = UIViewController()
        controller3.view.backgroundColor = .gray
        controllers.append(controller3)
        
        pageViewController = UIPageViewController()
        pageViewController.dataSource = self
        pageViewController.view.translatesAutoresizingMaskIntoConstraints = false
        pageViewController.view.heightAnchor.constraint(equalToConstant: 200).isActive = true

        addChild(pageViewController)
        contentView.addArrangedSubview(pageViewController.view)
        pageViewController.didMove(toParent: self)

        //
        
        let view2 = UIView()
        view2.translatesAutoresizingMaskIntoConstraints = false
        view2.heightAnchor.constraint(equalToConstant: 400).isActive = true
        view2.backgroundColor = .orange
        contentView.addArrangedSubview(view2)
    }
}

extension ViewController: UIPageViewControllerDataSource {
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        if let index = controllers.firstIndex(of: viewController), index > 0 {
          return controllers[index - 1]
        }
        return nil
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        if let index = controllers.firstIndex(of: viewController), index < controllers.endIndex - 1 {
            return controllers[index   1]
        }
        return nil
    }
    
    func presentationCount(for pageViewController: UIPageViewController) -> Int {
      return controllers.count
    }
      
    func presentationIndex(for pageViewController: UIPageViewController) -> Int {
      return 0
    }
}
 

Обратите внимание, что представления 1 и 2 отображаются правильно.

Ответ №1:

Решение было простым: создать UIPageViewController с некоторыми опциями и объявить первый контроллер представления.

 pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
pageViewController.setViewControllers([controllers.first!], direction: .forward, animated: false, completion: nil)