관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] PageViewController (페이지 뷰 컨트롤러) 본문

iOS 응용 (swift)

[iOS - swift] PageViewController (페이지 뷰 컨트롤러)

jake-kim 2021. 7. 15. 23:05

PageViewController 구현 원리

  • ViewController가 들어있는 배열을 준비
  • 첫번째 ViewController를 PageViewController에 set 초기화
  • 나머지 ViewController 전환은 DataSource, Delegate에서 index값을 바꿔가며 적용

PageViewController  구현

  • PageViewController위쪽에 위치할 NavigationView 정의
// ViewController.swift
class ViewController: UIViewController {

    lazy var navigationView: UIView = {
        let view = UIView()
        view.backgroundColor = .lightGray

        return view
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

    }
}
  • PageViewController에서 사용될 ViewControllers 준비
    lazy var vc1: UIViewController = {
        let vc = UIViewController()
        vc.view.backgroundColor = .red

        return vc
    }()

    lazy var vc2: UIViewController = {
        let vc = UIViewController()
        vc.view.backgroundColor = .green

        return vc
    }()

    lazy var vc3: UIViewController = {
        let vc = UIViewController()
        vc.view.backgroundColor = .blue

        return vc
    }()
    
    lazy var dataViewControllers: [UIViewController] = {
        return [vc1, vc2, vc3]
    }()
  • PageViewController 정의
    lazy var pageViewController: UIPageViewController = {
        let vc = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)

        return vc
    }()
  • layout 설정 함수 정의 (viewDidLoad에서 호출)
    • ContainerView를 따로 생성할 필요 없이 PageViewController 자체가 ContainerView
    • PageViewController의 top만 위 view의 bottom으로 설정해주면 한 화면에 부분적인 ViewController 표현 가능
    private func configure() {
        view.addSubview(navigationView)
        addChild(pageViewController)
        view.addSubview(pageViewController.view)

        navigationView.snp.makeConstraints { make in
            make.width.top.equalToSuperview()
            make.height.equalTo(72)
        }

        pageViewController.view.snp.makeConstraints { make in
            make.top.equalTo(navigationView.snp.bottom)
            make.leading.trailing.bottom.equalToSuperview()
        }
        pageViewController.didMove(toParent: self)

    }
  • pageViewController.setViewControllers()로 첫번째 ViewController만 set
        // viewDidLoad()에서 호출
        if let firstVC = dataViewControllers.first {
            pageViewController.setViewControllers([firstVC], direction: .forward, animated: true, completion: nil)
        }
  • PageViewControllerdelegate 설정 (viewDidLoad에서 호출)
    private func setupDelegate() {
        pageViewController.dataSource = self
        pageViewController.delegate = self
    }
  • Delegate 구현: 2개의 delegate를 정의하면 완료
    • viewControllerBefore: 왼쪽에서 오른쪽으로 스와이프 하기 직전에 호출 > 직전에 다음 화면에 어떤 ViewController가 표출될지 결정
    • viewControllerAfter: 오른쪽에서 왼쪽으로 스와이프 하기 직전에 호출 > 직전에 다음 화면에 어떤 ViewController가 표출될지 결정
extension ViewController: UIPageViewControllerDataSource, UIPageViewControllerDelegate {

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        guard let index = dataViewControllers.firstIndex(of: viewController) else { return nil }
        let previousIndex = index - 1
        if previousIndex < 0 {
            return nil
        }
        return dataViewControllers[previousIndex]
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        guard let index = dataViewControllers.firstIndex(of: viewController) else { return nil }
        let nextIndex = index + 1
        if nextIndex == dataViewControllers.count {
            return nil
        }
        return dataViewControllers[nextIndex]
    }
}

* source code: https://github.com/JK0369/PageViewControllerExample

 

* CollectionView + PageViewController로 ViewPager 만들기: https://ios-development.tistory.com/628

 

Comments