개발/Swift

[Swift] Tab bar 와 Page view를 동시에 사용할때

덤벨로퍼 2024. 5. 18. 13:40

문제

Tab bar 와 UIPageViewController

스와이핑이 가능하면서 동시에 탭바 선택으로 ViewController를 움직이고 싶을때

TabbarController 와 UIPageViewController 동시에 사용 할 경우 생각보다 예시가 많이 없고 정상 동작 하지 않았다.

TabbarController 는 또한 UI 커스텀이 쉽지 않았다.

 

해결

UIPageViewController 를 사용하여 페이지 관리 를 하고 ( 스와이프 가능 )

Tab Bar UI는 직접 커스텀하게 구현

 

구현

- TabBar 에서는 Rx 사용하여 클릭 이벤트 전달함

 

 

UIPageViewController 설정

private lazy var pageViewController = {
    let pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
    pageViewController.dataSource = self
    pageViewController.delegate = self
    return pageViewController
}()
private lazy var pages: [UIViewController] = [maleViewController, femaleViewController]
private let maleViewController = UserListViewController()
private let femaleViewController = UserListViewController()

 

UIPageViewController DataSource 및 Delegate 구현

 
extension ViewController: UIPageViewControllerDataSource, UIPageViewControllerDelegate {
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = pages.firstIndex(of: viewController), viewControllerIndex > 0 else {
            return nil
        }
        return pages[viewControllerIndex - 1]
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = pages.firstIndex(of: viewController),
              viewControllerIndex < pages.count - 1 else {
            return nil
        }
        return pages[viewControllerIndex + 1]
    }
    // 페이지 스와이핑 -> Tab bar 에 전달
    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
        if let visibleViewController = pageViewController.viewControllers?.first,
           let index = pages.firstIndex(of: visibleViewController) {
            tabButtonView.select(index: index)
        }
    }
    
}

Delegate 메소드를 통해 스와이핑 액션 발생시 페이지 return 구현 쉽게 가능 하며

현재 페이지 값을 탭바에 전달할수 있다.

 

 

Tab Bar 커스텀 및 이벤트 바인딩

 
    private let tabButtonView = TabButtonView(typeList: [.male, .female])
    
 tabButtonView.selectedType.bind { [weak self] type in
            guard let self = self else { return }
            switch type {
            case .male:
                pageViewController.setViewControllers([pages[0]], direction: .reverse, animated: true, completion: nil)
            case .female:
                pageViewController.setViewControllers([pages[1]], direction: .forward, animated: true, completion: nil)

            }
        }.disposed(by: disposeBag)

탭바 클릭시 이벤트를 전달받아서 Page ViewController 에 전달 해줌