기어가더라도 제대로
[UIKit-응용] Tab 전환을 모달로 하기(UITabBarController, Modal, Sheet) 본문
UIKit 기초
[UIKit-응용] Tab 전환을 모달로 하기(UITabBarController, Modal, Sheet)
Damagucci-juice 2025. 2. 4. 23:51구현 목표
스레드 앱처럼 탭 바 가운데에 + 버튼의 화면 전환이 모달식으로 구현하는 것이 목표
모달 탭바 컨트롤러 구현
- SceneDelegate에서 코드로 화면 구현
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(windowScene: windowScene)
window.rootViewController = SheetableTabBarController.shared
self.window = window
self.window?.makeKeyAndVisible()
}
}
- SheetableTabBarController 선언
class SheetableTabBarController: UITabBarController {
static let shared = SheetableTabBarController()
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
setupTabBar()
}
}
- TabBar Icon을 편하게 넣도록 인덱싱 열거형 객체를 중첩 타입으로 선언
// in SheetableTabBarController
// 탭바 선언용 인덱스 열거형
enum ViewControllerIndex: Int, CaseIterable {
case red = 0
case green
case blue
var name: String {
switch self {
case .red:
return "Red"
case .green:
return "Add"
case .blue:
return "Blue"
}
}
var image: String {
switch self {
case .red:
return "star.slash"
case .green:
return "plus.app"
case .blue:
return "moon.stars"
}
}
}
- setupTabBar 구현, 일반적으로 탭뷰 구성하는 것과 같음
- iOS 18에서 버그인지 확실하지 않으나 탭바 아이콘 표시가 안되어서 다른 방식으로 분기처리, 관련 유투브
// in SheetableTabBarController
func setupTabBar() {
// UITabBar 불투명하게 설정
let appearance = UITabBarAppearance()
// 불투명한 배경 설정
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = .white
tabBar.standardAppearance = appearance
// iOS 15 이상에서는 scrollEdgeAppearance도 설정해야 함
if #available(iOS 15.0, *) {
tabBar.scrollEdgeAppearance = appearance
}
// 뷰 생성
let redViewController = UIViewController()
redViewController.view.backgroundColor = .red
let redNaviController = UINavigationController(rootViewController: redViewController)
let dummyViewController = UIViewController()
let blueViewController = UIViewController()
blueViewController.view.backgroundColor = .blue
let blueNaviController = UINavigationController(rootViewController: blueViewController)
let viewControllers = [redNaviController, dummyViewController, blueNaviController]
// 뷰컨트롤러들을 탭바 뷰컨트롤러에 연결
setViewControllers(viewControllers, animated: false)
// 개별 탭바 아이콘 설정
if #available(iOS 18.0, *) {
let allViewIndex = ViewControllerIndex.allCases
for (index, child) in viewControllers.enumerated() {
let currentViewIndex = allViewIndex[index]
child.tabBarItem = UITabBarItem(
title: currentViewIndex.name,
image: UIImage(systemName: currentViewIndex.image),
tag: currentViewIndex.rawValue
)
}
} else {
if let items = tabBar.items, items.count < 3 {
ViewControllerIndex.allCases.forEach {
items[$0.rawValue].title = $0.name
}
}
}
}
- UITabBarControllerDelegate를 채택하여서 몇 번째 탭이 선택되었을 때 할 행동 선언
- shouldSelect 메서드를 선언해서 탭 선택을 미리 사전에 허용하거나 막기
- 주의⚠️: 매개변수로 전달받은 viewController를 직접 모달로 넘기려고하면 에러가 남
- 탭 화면을 생성해서 넘겨야함
extension SheetableTabBarController: UITabBarControllerDelegate {
func tabBarController(
_ tabBarController: UITabBarController,
shouldSelect viewController: UIViewController
) -> Bool {
if let viewControllers = tabBarController.viewControllers,
let index = viewControllers.firstIndex(of: viewController),
// 1번째 탭일 때
index == 1 {
// 초록색 뷰컨 설정
let modalVC = UIViewController()
modalVC.view.backgroundColor = .green
let modalNavigationController = UINavigationController(rootViewController: modalVC)
// 화면 전환 방식 지정
modalNavigationController.modalPresentationStyle = .pageSheet
if let sheet = modalNavigationController.sheetPresentationController {
sheet.detents = [.large()]
// 상단 손잡이 표시
sheet.prefersGrabberVisible = true
}
present(modalNavigationController, animated: true)
// 탭 방지
return false
}
// 이외 탭은 탭 허용
return true
}
}
전체 코드
'UIKit 기초' 카테고리의 다른 글
Comments