본문 바로가기
iOS/설명

[iOS] UIPageViewController

by Sky Titan 2022. 5. 21.
728x90
 

Apple Developer Documentation

 

developer.apple.com

 

 

 

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

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

ios-development.tistory.com

UIPageViewController

  • Android의 ViewPager와 유사하게 여러 Page를 navigating해서 이동할 수 있다.
  • 각 page를 관리하는 child viewController들 간의 navigation을 관리하는 container viewController이다.
  • page를 이동할 때 미리 지정한 transition style을 사용하여 animation을 보여준다.

 

예시

 참고로 Scroll을 할 때마다 Child ViewController들의 lifeCycle 메서드들도 정상적으로 호출됨(viewWillAppear, viewDidAppear, viewWillDisappear, ViewDidDisappear)

import UIKit

class ViewController: TSViewController {
    
    let blueViewController = BlueViewController()
    let redViewController = RedViewController()
    lazy var dataSources = [redViewController, blueViewController]
    
    lazy var pageViewController: UIPageViewController = {
        let pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal)
        pageViewController.delegate = self
        pageViewController.dataSource = self
        pageViewController.setViewControllers([redViewController], direction: .forward, animated: true)
        return pageViewController
    }()
    
    lazy var segmentControl: UISegmentedControl = {
        let control = UISegmentedControl(items: ["firstView", "secondView"])
        control.backgroundColor = .white
        control.tintColor = .lightGray
        control.addTarget(self, action: #selector(segmentChanged(_:)), for: .valueChanged)
        control.translatesAutoresizingMaskIntoConstraints = false
        control.selectedSegmentIndex = 0
        return control
    }()
    
    private(set) var currentIndex: Int = 0
    @objc
    func segmentChanged(_ secon: UISegmentedControl) {
        pageViewController.setViewControllers([dataSources[secon.selectedSegmentIndex]], direction: secon.selectedSegmentIndex <= currentIndex ? .reverse : .forward, animated: true)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        
        
        addChild(pageViewController)
        view.addSubview(pageViewController.view)
        
        pageViewController.view.addSubview(segmentControl)
        
        NSLayoutConstraint.activate([
            pageViewController.view.safeAreaLayoutGuide.topAnchor.constraint(equalTo: segmentControl.topAnchor),
            segmentControl.heightAnchor.constraint(equalToConstant: 50),
            pageViewController.view.leadingAnchor.constraint(equalTo: segmentControl.leadingAnchor),
            pageViewController.view.trailingAnchor.constraint(equalTo: segmentControl.trailingAnchor)
        ])
    }
}

extension ViewController: UIPageViewControllerDelegate, UIPageViewControllerDataSource {
    func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
        // 이동하기 전 호출
        print("will trainsition to \(pendingViewControllers.first)")
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
        // trainsition Animtion 완료된 후 호출 (직전 child)
        print("did finish animating \(previousViewControllers.first)")
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        //왼쪽에서 오른쪽으로 이동하기 직전, 다음 viewController 반환
        if let index = dataSources.firstIndex(of: viewController), index + 1 < dataSources.count {
            currentIndex = index + 1
            return dataSources[index + 1]
        }
        return nil
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        //오른쪽에서 왼쪽으로 이동하기 직전, 이전 viewController 반환
        if let index = dataSources.firstIndex(of: viewController), index - 1 >= 0 {
            currentIndex = index - 1
            return dataSources[index - 1]
        }
        return nil
    }
}

728x90

'iOS > 설명' 카테고리의 다른 글

[iOS] App의 상태 별 Silent Push의 동작  (0) 2022.05.25
[iOS] Register Push Device Token  (0) 2022.05.25
[iOS] UIView와 CALayer의 차이  (0) 2022.05.21
[iOS] Rest API 테스트 사이트  (0) 2022.05.21
[iOS] URLSession  (0) 2022.05.16

댓글